C - 使用fork()和exec()两次

时间:2017-01-17 19:14:56

标签: c linux

我有以下代码:

int main(int argc, char **argv)
{
    char    *program;
    char     stringa[1000] = "";
    int num = 123;
    char snum[10];

    if (argc != 2) {
        printf("Usage: mon fileName\n where fileName is an executable file.\n");
        exit(-1);
    } else {
        program = argv[1];
        sprintf(stringa, "./%s", program);

        pid_t pid = fork();
        if (pid < 0 ) {
            perror("fork failed."); 
            exit(1); }

        else if (pid == 0) {
            char* args[] = {stringa, NULL};
            execv(args[0], args);
        }
        else {

            char procmon_str[] = "./procmon";
            num = pid;
            sprintf(snum, "%d",num);
            pid_t pid2 = fork();
            if (pid2 == 0) {
                char* args2[] = {procmon_str, snum, NULL};
                execv(args2[0], args2); }
            else {

                printf("PID of child is %s", snum);
                int parent_pid = getpid(); 
                printf("PID of parent is %d", parent_pid);}

        }}
    wait(NULL);

    return 0;
}

此计划的名称为myProgram。我在shell中提供的参数是:

./myProgram calc

calc是我要使用myProgram启动的另一个程序。 myProgram然后calc执行PID,将PID传递给另一个名为procmon的程序,该程序对其执行某些操作;这就是为什么我需要分叉两次。 但是,当我运行上面的代码时,我得到:

procmon: cannot open /proc/6225/stat, the monitored process is not running anymore

我该如何解决这个问题?

calc做什么? 它进入for循环,递增int变量并进入睡眠状态3秒并重复10次。所以它应该运行大约30秒。

procmon做什么? procmon只接收PID进程作为参数,并显示相应的/proc/PID/stat文件。当你自己运行时,它可以很好地工作。

3 个答案:

答案 0 :(得分:5)

你有竞争条件。在calc子进程完成执行并退出之前,您无法保证第一个fork()实际上甚至会返回到您的父进程。您需要同步流程的执行。

有关阻止和发出信号的地方的ETA建议

if (pid == 0) 
{
    // block here waiting for the go-ahead from parent
    char* args[] = { stringa, NULL };
    execv( args[ 0 ], args );
}

......

else
{
    // signal calc child here 
    printf( "PID of child is %s", snum );
    int parent_pid = getpid();
    printf( "PID of parent is %d", parent_pid );
}

学习如何通过进程间通信来阻止和发出信号是留给提问者的练习。

答案 1 :(得分:2)

一开始没注意到......

您的主要进程是创建两个子进程,proc和prcmon。 你的问题是由于竞争条件和调度 - calc首先完成,所以你想要做的是强迫calc等待它的兄弟进程。你只能在你创建的进程上等待()所以这样你就不能让calc等待prcmon完成。

<强> BUT

您可以实现一些机制使父进程等待其子进程,然后通过管道将返回数据传递给其他子进程。在你的情况下,我不确定。你想在prcmon中得到calc的PID并显示它吗?我不知道这是否可能,因为一旦完成计算,其描述符将被删除并且不再存在。

你的问题的一个解决方案是让calc做大量的计算,因为你只需要它活着而不是它的返回值。

答案 2 :(得分:0)

所以没有注意到,我的程序提供了正确的输出。 我的程序名为myProgram,它的启动方式如下:

./myProgram calc

calc是一个运行30秒的程序进行一些基本的数学运算,没什么太疯狂的。 然后,启动另一个进程procmonprocmon获取PID的{​​{1}}并打印文件:

calc

究竟发生了什么。我收到该文件到我的shell,这意味着/proc/calc-PID/stat calc都成功运行。 出于某种原因,我认为在运行此程序后我应该在系统中获得一个新文件,所以我甚至不太关注shell中发生的事情。

我真的很抱歉它可能对某些人造成的混乱,我一定会记住在问之前再检查我的问题1000次。

我也非常感谢大家的帮助和支持,成为这个社区的一员真是太棒了!