我正在尝试制作一个模仿Linux shell的程序。
它以两种模式运行
(1)交互模式(无参数)
等待子进程。一次执行一个命令。
(2)批处理模式(给定文件)
不要等。尝试并行执行命令。
我的代码很长,所以我决定制作一个示例程序来解决(关注)我所面临的问题。
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
struct commands
{
char *cmd[2];
};
int main(int argc, char *argv[])
{
printf("A program made to understand execvp\n");
commands threeCommands[3];
pid_t process;
int child_status;
threeCommands[0].cmd[0] = "date";
threeCommands[0].cmd[1] = NULL;
threeCommands[1].cmd[0] = "pwd";
threeCommands[1].cmd[1] = NULL;
threeCommands[2].cmd[0] = "cal";
threeCommands[2].cmd[1] = NULL;
for(int i = 0;i <3;i++)
{
process = fork();
if(process == 0)
{
execvp(threeCommands[i].cmd[0],threeCommands[i].cmd);
}
else
{
//wait(&child_status);
}
}
return 0;
}
正如你所看到的,我正在评论等待,以便我尝试进行并发处理,并且命令的结果是随机的,也许是混合的。
问题出在执行三个命令date,pwd,cal
该程序没有终止。它在这种状态下冻结并且不会结束,所以我的光标就像它需要输入一样。而我的计划并没有结束。我该如何解决这个问题?
我应该使用kill还是什么?
答案 0 :(得分:1)
输出后只需按 Enter 键即可。
如果父进程在子进程之前退出,那么shell将在父进程退出后打印提示,然后子进程打印输出,但shell不会打印新的提示。查看输出结尾上方的几行,以在父进程退出后查看提示。
例如,在修改代码以在调用sleep(1)
之前添加execvp
(以强制延迟子进程)之后,我在系统上得到以下输出:
[~/tmp]$ ./a.out A program made to understand execvp [~/tmp]$ tis 9 feb 2016 18:54:06 CET /home/XXXX/tmp Februari 2016 sö må ti on to fr lö 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
如您所见,在date
命令运行之前打印提示(.[~/tmp]$
输出之前的date
。按 Enter 会返回提示。
答案 1 :(得分:0)
您必须调用wait
才能使子进程干净地终止。您不必立即致电wait
,但必须在程序结束前致电wait
,否则您将拥有僵尸子进程。这对我有用,并且仍然并行运行所有程序:
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
struct commands
{
char *cmd[2];
};
int main(int argc, char *argv[])
{
printf("A program made to understand execvp\n");
struct commands threeCommands[3];
pid_t process;
int child_status;
threeCommands[0].cmd[0] = "date";
threeCommands[0].cmd[1] = NULL;
threeCommands[1].cmd[0] = "pwd";
threeCommands[1].cmd[1] = NULL;
threeCommands[2].cmd[0] = "cal";
threeCommands[2].cmd[1] = NULL;
for(int i = 0;i <3;i++)
{
process = fork();
if(process == 0)
{
execvp(threeCommands[i].cmd[0],threeCommands[i].cmd);
}
}
for(int i = 0;i <3;i++)
{
wait(&child_status);
}
return 0;
}
另一种选择是忽略SIGCHLD
信号:
signal(SIGCHLD, SIG_IGN); // automatically reap child processes