【发布时间】:2016-10-30 20:14:26
【问题描述】:
我要做的是运行一个程序并返回整个输出并一次打印一行结果。
当我使用 a.out 作为参数执行程序时,到目前为止一切正常,直到我开始尝试从管道中读取更多数据。我收到以下结果:
Line 0:
Line 1:
MCS-51 Family Macro Assembler ASEM-51 V1.3
Line 2:
Line 3:
a.out(1): illegal character
Line 4:
a.out(2): illegal character
Line 5:
a.out(3): illegal character
Line 6:
a.out(4): illegal character
Line 7:
a.out(5): illegal character
Line 8:
a.out(5): no END statement found
Line 9:
Line 10:
6 errors detected
Line 11:
Application tried to create a window, but no driver could be loaded.
Line 12:
Make sure that your X server is running and that $DISPLAY is set correctly.
Line 13:
err:systray:initialize_systray Could not create tray window
Line 14:
但是,第 11 到 14 行根本不应该出现,因为我执行的远程程序在打印第 10 行的内容后完成。
请忽略非法字符语句。这是因为我正在制作一个执行第三方汇编程序的程序,并且我正在传递无效的源代码。
我试图添加一个字符代码 255 以从子级输出回父级,但我无法在父级中接收它,但是如果我尝试在我的系统上执行一个不存在的文件,我会能够将单词“ERROR”发送回父级并在父级中检索它。
我不知道我在这里做错了什么,但我正在尝试找到一种方法来确定何时停止尝试读取更多数据,直到父级从子级接收垃圾而不是真正的输出.
我该如何解决这个问题?
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
char line[100][512];
int numlines=0;
int run(char* dir,char* mainapp,char *par1,char *par2){
int pf[2]; //pf = PipeFields
pipe(pf);
if (fork()==0){
//CHILD START
//cmdline = commandline to program = directory (dir) + / + main app name + padded nulls
char cmdline[10000];
memset(cmdline,0,10000);
strcat(cmdline,dir);
strcat(cmdline,"/");
strcat(cmdline,mainapp);
char *args[5]={cmdline,par1,par2,NULL}; //arguments to program
close(pf[0]);
//redirect all output streams to same place
dup2(pf[1],1);
dup2(pf[1],2);
//return error as part of output if program can't execute
if (execve(cmdline,args,NULL) < 0){write(pf[1],"ERROR",5);}
//return ascii character as last byte to output back to caller
write(pf[1],(unsigned char*)255,1);
close(pf[1]);
//CHILD END
}else{
//b = buffer
memset(line,0,51200); //clear all lines of output
char b[102400];
memset(b,0,102400); //clear temporary buffer
char *b2=b; //make reference to buffer for strcat
char incoming[10001]; //incoming buffer of 10000 bytes of data plus null
close(pf[1]); //don't need to write to child. close pipe.
long hasdata=0,sz=0;
while((sz=read(pf[0],incoming,sizeof(incoming)-1)) > 0){
//execute this while incoming pipe has between 1 and 10000 bytes of data
printf(">>> %ld >> %s\n",sz,incoming); // <-- show output for debugging
incoming[sz]='\0'; //add null to end of incoming data so strcat can work
strcat(b2,incoming); //add incoming data to main buffer
hasdata=1; //we have data
//see if incoming data contains magic character code 255 as a byte
if (strchr(incoming,255)){
//but this never gets executed? what's going on???
printf("BREAKKKKK");
break;
}
}
//if theres data then convert it into lines
if (hasdata==1){
numlines=0; //reset number of lines
char *bp=b; //make reference to data
char *thisln=line[0]; //make reference to line
while(*bp){
if(*bp=='\n'){ //if theres a new line,...
numlines++; //increment counter...
if (numlines > 100){break;} //and exit if theres too many lines
thisln=line[numlines]; //make reference to next line
}
*thisln=*bp; //transfer bytes 1 by 1 to appropiate areas
bp++; //and increment pointer
thisln++;
}
}
close(pf[0]);
}
return 0;
}
int main(int argc,char *argv[]){
int thisline;
//get 2 arguments
if (argc < 2){printf("Filename required\n");return -1;}
//make sure argument is valid file
if (access(argv[1],R_OK) < 0){printf("File not found: %s\n",argv[1]);return -2;}
//run app
run("/usr/bin","wine","/DOS/8051asm/asemw.exe",argv[1]);
//print results line by line
for (thisline=0;thisline<=numlines;thisline++){
printf("Line %d: %s\n",thisline,line[thisline]);
}
return 0;
}
【问题讨论】:
-
作为一种解决方法,您可以尝试设置和导出
WINEDEBUG=err-systray,这将阻止wine 将系统托盘错误输出到fd 2。 -
为了便于阅读和理解:1) 通过空行分隔代码块(for、if、else、while、do...while、switch、case、default) 2) 一致缩进代码。在每个左大括号 '{' 后缩进。在每个右大括号 '}' 之前不缩进。切勿使用制表符进行缩进,建议每个缩进级别使用 4 个空格,因为这很容易看到,即使是可变宽度字体。
-
fork()函数实际上返回三种不同的指示:>0 表示父项,==0 表示子项, -
函数:
execvp()仅在发生错误时返回。所以在调用execvp()之后的任何事情都应该只调用perror();后跟exit( EXIT_FAILURE ); -
子进程只能由
exit()或_exit()终止,不允许(在if/then/else 结束后)更多只应由父进程执行的代码.