进程间通信fork() - 定时wait()和/或sleep()

时间:2013-08-05 08:36:47

标签: c unix fork ipc wait

我被要求将生产者(客户端)开发给生产者(服务器),生产者创建流程,等待消费者读取共享内存和删除流程,然后将控制权交还给生产者。杀死进程并关闭共享内存块。

我研究了睡眠和等待之间的区别,并意识到只要调用fork(),子进程就会开始运行。

以下代码是在创建流程之后检查它们是否是父流程。如果是,他们等待(0)。 *现在我的问题是,如何知道消费者中的代码开始执行的位置,以及如何将其传回去? *

else if(pid > 0)
                {
                    wait(0);
                }

下面可以看到生产者使用的主循环。

int noToCreate = atoi(argv[2]); // (user inputs on cmd line "./prod 20 10 5" - 20 size of shared mem, 10 process to be created, 5 processes to be deleted)

while(*memSig != 2)
    {
        while(*memSig == 1)   // set memsignature to sleep while..
        {
            sleep(1);
        }

        for(B = 0; B < noToCreate; B++)     
        {
            pid = fork();

            if(pid == -1)
            {
                perror("Error forking");
                exit(1);
            }
            else if(pid > 0)
            {
                wait(0);
            }
            else
            {
                srand(getpid());

                while(x == 0)
                {
                    if(*randNum == 101)
                    {
                        *randNum = rand() % (100 - 

1) + 1;
                        *pidNum = getpid();

                        printf("priority: %d 

Process ID: %d \n", *randNum, *pidNum);

                        x = 1;
                    }
                    else
                    {
                        *randNum++;
                        *pidNum++;
                    }
                }
                exit(0);
            }
        } /* Closes main for loop */

        if(*memSig == 0)
        {
            *memSig = 1;
        }
    } /* Closes main while loop */

谢谢一群人:)

3 个答案:

答案 0 :(得分:2)

wait让父母被阻止,直到任何孩子结束。你可以使用waitpid让父母等待特定的孩子。

当子进程结束时,它将设置信号SIG_CHILD

答案 1 :(得分:2)

fork之后的子进程的pid为零,因此您在调用srand函数时处于子进程中。

另一个pid是对于允许原始线程等待孩子完成的子进程。如果您希望在进程之间传递数据,请考虑使用管道。 popen调用返回两个文件描述符,一个用于写入结束,另一个用于读取结束。在fork之前设置它,并且两个进程可以通信。

答案 2 :(得分:1)

wait让父母等待任何孩子在继续之前终止(最好使用waitpid等待某个孩子),而sleep让进程进入休眠状态并恢复它,一旦论证结束时间过了。
这两个调用都会使进程阻止 并且 NOT 表示孩子会立即跑,这是不确定的行为!

如果要在生产者和使用者之间传递数据,请使用管道或* NIX套接字,或者如果单个整数足够,则使用子进程中exit的返回值。

请参阅man wait,您可以使用宏WEXITSTATUS获取子项的返回值。

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

int
main(int argc, char *argv[])
{
    pid_t cpid, w;
    int status;

   cpid = fork();
    if (cpid == -1) {
        perror("fork");
        exit(EXIT_FAILURE);
    }

   if (cpid == 0) {            /* Code executed by child */
        printf("Child PID is %ld\n", (long) getpid());
        if (argc == 1)
            pause();                    /* Wait for signals */
        _exit(atoi(argv[1]));

   } else {                    /* Code executed by parent */
        do {
            w = waitpid(cpid, &status, WUNTRACED | WCONTINUED);
            if (w == -1) {
                perror("waitpid");
                exit(EXIT_FAILURE);
            }

           if (WIFEXITED(status)) {
                printf("exited, status=%d\n", WEXITSTATUS(status));
            } else if (WIFSIGNALED(status)) {
                printf("killed by signal %d\n", WTERMSIG(status));
            } else if (WIFSTOPPED(status)) {
                printf("stopped by signal %d\n", WSTOPSIG(status));
            } else if (WIFCONTINUED(status)) {
                printf("continued\n");
            }
        } while (!WIFEXITED(status) && !WIFSIGNALED(status));
        exit(EXIT_SUCCESS);
    }
}