我正在编写一个模仿shell行为的代码,特别是&和|。
我的功能接收用户命令,并检查是否有&最后,子进程应该在后台运行,父进程不应该等待它完成并继续执行命令。
还应该检查是否有|在输入数组中运行两个子进程,同时管道他们的stdin和stdout。
我已经实现了&的行为,但每当我编译并运行我的代码时,我只从父进程获得printf语句。
我想听听如何解决此问题的想法,此外,我将不胜感激任何关于|的实施的建议(管道)以及如何防止僵尸。
int process_arglist(int count, char** arglist) {
int pid = fork();
printf("%d", pid);
switch (pid) {
case -1:
fprintf(stderr, "ERROR: fork failed\n");
return 1;
break;
case 0: // Son's proccess
printf("I got to son");
//check last arglist argument
if (strcmp(arglist[count - 1], "&") == 0) {
setpgid(0, 0);
arglist[count - 1] = NULL;
if (execvp(*arglist, arglist) < 0) { //execute the command
fprintf(stderr, "ERROR: execvp failed\n");
exit(1);
}
} else { //There's no & at the end, look for pipes
int i = 0;
while (i < count) {
if (strcmp(arglist[i], "|") == 0) {
int pid2 = fork();
if (pid2 < 0) {
//fork failed, handle error
}
if (pid2 == 0) { // Son's proccess
} else { //Parent's code
}
}
}
}
break;
//in case no & and no |, call execvp
default: //Parent's code
printf("I go to parent");
return 1;
break;
}
return 0;
}
输出始终是“我去父母”
答案 0 :(得分:2)
我假设您的代码适用于Linux或其他POSIX系统。阅读一些关于Linux编程的好书(可能是旧的Advanced Linux Programming,可以免费下载,或者更新的东西。)
stdio(3)已缓冲,stdout
和printf
通常(但并非总是)进行行缓冲。出于效率原因进行缓冲(经常调用write(2),例如每个输出字节一次,非常慢;您应该更喜欢在几千字节的块上执行write
- s)。
顺便说一句,您最好使用system calls至intro(2)(或syscalls(2)来处理errno(3)(请参阅perror(3)和strerror(3))的失败在errno
)。您(以及您的shell的用户)需要被告知失败原因(并且您当前的代码没有显示它)。
我建议您经常使用printf
结束\n
格式控制字符串(这在stdout行缓冲时有效)或在适当的位置调用fflush(3)。
根据经验,我建议在每次拨打fork(2)之前执行fflush(NULL);
。
您观察到的行为与某些printf
数据停留在缓冲区(例如stdout
)的假设一致。
您可以在程序中使用strace(1)(或在其他程序上使用{3}},以了解system calls已完成的内容。
您应编译所有警告和调试信息(例如gcc -Wall -Wextra -g
与GCC),改进您的代码以获取警告,use the debugger gdb
(小心,它可以用于分叉过程)。
我正在编写一个模仿shell行为的代码
你可能正在编写一些shell。然后研究获取现有free software shell的源代码(大多数 - 可能是所有Linux shell都是免费软件)。
我很感激有关|的实施的任何建议(管道)以及如何防止僵尸。
解释所有需要大量空间(书的几个章节,或者整本书)和不适合或任何其他论坛。所以阅读一本好的Linux 或POSIX 编程书。关于管道,请阅读pipe(7)(应在<{em> fork
之前使用pipe(2) 创建。{关于避免zombie processes,您需要仔细拨打waitpid(2)或类似的电话。