C 进程终止不';不影响waitpid()

C 进程终止不';不影响waitpid(),c,linux,operating-system,system-calls,C,Linux,Operating System,System Calls,我需要在Linux下使用C模拟以下bash命令(使用fork、exec、kill、signal、wait、waitpid、dup2、open、sleep、pipe等) 到目前为止,我有以下代码: #include <fcntl.h> #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/wait.h> int main(int argc,

我需要在Linux下使用C模拟以下bash命令(使用fork、exec、kill、signal、wait、waitpid、dup2、open、sleep、pipe等)

到目前为止,我有以下代码:

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>  
#include <sys/wait.h> 

int main(int argc, char *argv[]) {
    pid_t pID = fork();
    if (pID == 0) // child
    {
        int file = open("/tmp/rtail", O_CREAT | O_WRONLY);

        //Now we redirect standard output to the file using dup2
        dup2(file, 1);

        puts("tail -f $1");
        close(file);
        system("chmod 777 /tmp/rtail");
        exit(0);
    } else if (pID < 0) // failed to fork
    {
        printf("Failed to fork");
        exit(1);
        // Throw exception
    } else // parent
    {
        pid_t pID2 = fork();
        if (pID2 == 0) {
            char tmp1[20];
            sprintf(tmp1, "echo %i > /tmp/pidprog1", getpid());
            system(tmp1);


            int file = open("/tmp/1.txt", O_APPEND | O_WRONLY);

            //Now we redirect standard output to the file using dup2
            dup2(file, 1);
            FILE* proc = popen("sh /tmp/rtail ~/.bash_history", "r");
            char tmp[20];
            while (fgets(tmp, 40, proc) != NULL) {
                printf(tmp);
            }
            fclose(proc);

            exit(0);
        }
        else if (pID2 < 0) // failed to fork
        {
            printf("Failed to fork");
            exit(1);
            // Throw exception
        } else {
            FILE* fl = fopen("/tmp/pidprog1", "r");
            char buff[10];
            fgets(buff, 10, fl);
            int pidc = atoi(buff);
            fclose(fl);
            int status;
            waitpid(pidc, &status, 0);
            printf("Program 1 terminated\n");
        }
    }

    // Code executed by both parent and child.  

    return 0;
}
#包括
#包括
#包括
#包括
#包括
int main(int argc,char*argv[]){
pid_t pid=fork();
if(pID==0)//子级
{
int file=open(“/tmp/rtail”,O|u CREAT | O|u WRONLY);
//现在,我们使用dup2将标准输出重定向到文件
dup2(文件,1);
看跌期权(“尾价-1美元”);
关闭(文件);
系统(“chmod 777/tmp/rtail”);
出口(0);
}else if(pID<0)//分叉失败
{
printf(“未能分叉”);
出口(1);
//抛出异常
}else//parent
{
pid_t pID2=fork();
如果(pID2==0){
char-tmp1[20];
sprintf(tmp1,“echo%i>/tmp/pidprog1”,getpid());
系统(tmp1);
int file=open(“/tmp/1.txt”,O_APPEND | O_WRONLY);
//现在,我们使用dup2将标准输出重定向到文件
dup2(文件,1);
文件*proc=popen(“sh/tmp/rtail~/.bash_history”,“r”);
char-tmp[20];
while(fgets(tmp,40,proc)!=NULL){
printf(tmp);
}
fclose(proc);
出口(0);
}
else if(pID2<0)//分叉失败
{
printf(“未能分叉”);
出口(1);
//抛出异常
}否则{
文件*fl=fopen(“/tmp/pidprog1”,“r”);
字符buff[10];
fgets(浅黄色,10,fl);
int-pidc=atoi(buff);
fclose(fl);
智力状态;
waitpid(pid,状态为0);
printf(“程序1已终止\n”);
}
}
//由父级和子级执行的代码。
返回0;
}

问题是,当我使用保存到/tmp/pidprog1中的PID手动终止进程时,父进程不会停止等待,也不会打印“程序1已终止”行。

父进程很可能正在将垃圾值读入pidc。您没有做任何事情来确保在父对象尝试读取pid之前,孙辈已经实际编写了pid。您需要使用wait来确保文件中存在有效的PID。(或者,只需从fork的返回值跟踪PID即可。)

您没有进行足够的错误检查:如果任何打开失败会发生什么?(例如,当你尝试时 要打开/tmp/1.txt进行追加,但它还不存在?)

为什么要使用FGET将40个字符读入大小为20的缓冲区

为什么您要复制和使用FPUT,而不仅仅是向fd写入


为什么要将错误消息打印到stdout而不是stderr(使用peror)。

如果写入文件的全部目的是保存孙子的PID,那么如何等待孙子呢?大多数错误都是由于代码的草稿阶段造成的。我使用dup而不是直接写入文件,因为我认为任务明确表示我更喜欢这种方法。@bvk256使用wait来等待,直到子项完成。但你为什么要从文件中获取pid?它由fork()返回。将外子代的pid传递给父代需要做更多的工作,通常通过管道而不是文件系统完成。你需要某种同步。使用wait,或者打开管道,或者使用其他形式的IPC。您的家庭作业是否指定pid应保存在文件中,或者只是说“pid…应保存”。根本不需要保存它,因为它是由wait返回的,并且将它保存在文件中是非常不寻常的。将其存储在变量中。调用wait并使用返回值,忽略存储值。还有第二部分赋值,应创建第二个程序,并在一段时间后使用保存的PID杀死第一个程序。因此,第二个程序需要写入文件才能知道第一个程序的PID。
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>  
#include <sys/wait.h> 

int main(int argc, char *argv[]) {
    pid_t pID = fork();
    if (pID == 0) // child
    {
        int file = open("/tmp/rtail", O_CREAT | O_WRONLY);

        //Now we redirect standard output to the file using dup2
        dup2(file, 1);

        puts("tail -f $1");
        close(file);
        system("chmod 777 /tmp/rtail");
        exit(0);
    } else if (pID < 0) // failed to fork
    {
        printf("Failed to fork");
        exit(1);
        // Throw exception
    } else // parent
    {
        pid_t pID2 = fork();
        if (pID2 == 0) {
            char tmp1[20];
            sprintf(tmp1, "echo %i > /tmp/pidprog1", getpid());
            system(tmp1);


            int file = open("/tmp/1.txt", O_APPEND | O_WRONLY);

            //Now we redirect standard output to the file using dup2
            dup2(file, 1);
            FILE* proc = popen("sh /tmp/rtail ~/.bash_history", "r");
            char tmp[20];
            while (fgets(tmp, 40, proc) != NULL) {
                printf(tmp);
            }
            fclose(proc);

            exit(0);
        }
        else if (pID2 < 0) // failed to fork
        {
            printf("Failed to fork");
            exit(1);
            // Throw exception
        } else {
            FILE* fl = fopen("/tmp/pidprog1", "r");
            char buff[10];
            fgets(buff, 10, fl);
            int pidc = atoi(buff);
            fclose(fl);
            int status;
            waitpid(pidc, &status, 0);
            printf("Program 1 terminated\n");
        }
    }

    // Code executed by both parent and child.  

    return 0;
}