使用execlp调用cut命令出现额外空行问题排查
问题原因及解决办法
额外空行的根源
你给cut传的参数错了。在child1里,你写的char *d="-d " "";会拼成"-d "(也就是-d后面带个空格),然后作为单个参数传给cut。但cut的-d选项要求选项和分隔符是两个分开的参数——正确姿势是把"-d"当一个参数,空格" "当另一个参数。
这种错误的参数传递会让cut解析混乱,输出就会多出来空行,和你在终端直接执行的效果不一样。
子进程卡着不退出的原因
父进程没关管道的两端!子进程1退出后,管道的写端还被父进程握着,子进程2的read就会一直等数据,直到所有写端都关闭才会返回0、结束循环。这就是为啥你的程序要等超时才能结束。
改好后的代码
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> #include <time.h> #include <string.h> #include <fcntl.h> #include <signal.h> void wait_child() { int terminated, status; terminated=wait(&status); if (WIFEXITED(status)) { printf("Child termination ok\n"); }else if (WIFSIGNALED(status)) { printf("Child termination not ok\n"); } } void child1(int ppwrite, char* file) { char *f="-f2"; // 提取每行第二个字段 dup2(ppwrite,1); // 把stdout转到管道写端 close(ppwrite); // 修正cut参数:-d和空格分开传 execlp("cut","cut", "-d", " ", f, file, (char*)0); perror("exec error"); } void child2(int ppread) { int nread,nlines; char buffer; nlines=0; printf("Line 1: "); while ((nread=read(ppread, &buffer, sizeof(buffer)))>0) { if (buffer=='\n') { nlines++; printf("\n"); // 看看后面还有没有数据,有再打印下一行的提示 char next; if (read(ppread, &next, 1) == 1) { lseek(ppread, -1, SEEK_CUR); printf("Line %d: ", nlines+1); } } else { printf("%c", buffer); } } close(ppread); printf("\n"); } void handler(int signum) { if (signum==SIGALRM) { printf("Timeout\n"); exit(EXIT_SUCCESS); } } int main(int argc, char* argv[]) { int pid1,pid2; int pp[2]; if (pipe(pp)<0) { printf("Errore creazione pipe\n"); exit(EXIT_FAILURE); } signal(SIGALRM, handler); alarm(5); pid1=fork(); if (pid1<0) { printf("P1 could not be created\n"); exit(EXIT_FAILURE); } else if (pid1==0) { close(pp[0]); child1(pp[1], "myfile.txt"); } else { pid2=fork(); if (pid2<0) { printf("P2 could not be created\n"); exit(EXIT_FAILURE); } else if (pid2==0) { close(pp[1]); child2(pp[0]); } else { // 父进程必须关管道两端,不然子进程2会一直等 close(pp[0]); close(pp[1]); for (int i=0; i<2; i++) { wait_child(); } } } }
核心改动点
cut参数修复:把原来的"-d "拆成"-d"和" "两个参数,让cut正确识别空格分隔符,解决额外空行问题。- 父进程关闭管道:主进程里fork完两个子进程后,立刻关闭管道的读写端,这样子进程1退出后,管道写端完全关闭,子进程2的
read会返回0,正常结束循环。 - 输出优化:读取到换行符时,先检查管道里还有没有后续数据,只有有数据才打印下一行的
Line X:提示,避免最后多出一行空的提示。
内容的提问来源于stack exchange,提问作者Chiara Busca
相关产品推荐
相关产品推荐

