【问题标题】:Parallel processing and synchronization using semaphores in C [closed]在 C 中使用信号量进行并行处理和同步 [关闭]
【发布时间】:2016-01-02 20:16:31
【问题描述】:

问题:

  1. 我的进程是否并行运行? 我想要六个进程并行运行。
  2. 如何在无限循环中使用信号量同步这些进程(父进程和五个子进程)?所以输出将是: 1 2 3 4 5 reset 1 2 3 4 5 reset 等...
  3. 任何简单易懂的信号量文档?

代码:

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

parentWithFiveChildren()
{   
    printf("1 "); //Parent
    fflush(stdout);

    int i, status;

    for (i = 2; i < 7; i++)
    {   
        sleep(1); 
        if (fork() == 0) //Child Processes
        {               
            if (i == 6) 
            {
                printf("reset "); 
                fflush(stdout);
                exit(0);
            }
            printf("%d ", i); 
            fflush(stdout);
            sleep(7); 
            exit(i); //Exiting child processes
        }
    }

    while ((wait(&status)) > 0)
    printf("\a");
    return 0;
}

int main(void)
{
    parentWithFiveChildren();
}

输出:

1 2 3 4 5 reset

【问题讨论】:

  • 这些问题的答案在 C 领域和 POSIX 领域之外(如果您点击了“fork”标签来阅读标签 wiki,您就会知道),等等事物。你有六个处理器内核吗?如果没有,是否甚至可以同时运行六个进程,而不是在它们之间进行任务切换?我希望这个评论已经为你提供了足够的思考,让你去做一些研究并自己想出答案。如果这对您来说太容易了,那么请考虑“过早的优化是万恶之源”并问自己,为什么fork()
  • @Seb - 这些问题的答案不在 C 领域和 POSIX 领域中。 1) 可能,但考虑到上下文问题和提问者的经验水平,2) 和 3) 都在 C 的范围内。
  • @ryyker 关于 2,C 没有定义术语“进程”;这也是一种 POSIX 主义。
  • 这里真的有什么东西表明反对票或接近票吗?该问题格式正确,格式正确,具有一定程度的特异性,并且将来可能对其他人有用。是不是应该考虑海报对网站和工艺的体验?
  • @ryyker:我添加了posixunix 标签来消除“这不是纯标准C”的一些不必要的迂腐反对意见,尽管fork 已经这样做了。我同意这是一个相当不错的问题,提出了一个可以回答(不太宽泛)的问题。

标签: c unix parallel-processing fork posix


【解决方案1】:

1。并行性

不,这些进程没有并行运行(或者,至少,它们只是暂时并行运行,并且一次只有两个进程),但是这仅仅是因为:

  1. sleep(1) 使父进程有很长时间(至少一秒钟)什么都不做。
  2. 孩子在那一秒内完成并退出。

您在孩子身上的打印代码是奇怪的; i == 6 和其他操作之间实际上没有区别。在main()return 0;exit(0); 中实际上是相同的——可能存在差异,但它们是模糊的,并且与您的代码无关。

你应该#include &lt;sys/wait.h&gt;,你应该收集死去孩子的PID(和状态);它会让你更清楚。

您也可以让孩子报告睡眠一段时间(比如每个 7 秒)。这将使您所有子进程并行“运行”(实际上是睡眠),然后父进程等待子进程退出:

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

int main(void)
{
    printf("[PARENT] with pid %d\n", getpid()); 
    fflush(stdout);

    for (int i = 2; i < 7; i++)  // Odd loop conditions, but not wrong
    {   
        sleep(1); 
        if (fork() == 0)
        {   
            printf("[CHILD] with pid %d from parent with pid %d\n", getpid(), getppid()); 
            fflush(stdout);
            sleep(7);
            printf("[CHILD] with pid %d exiting with status %d\n", getpid(), i); 
            exit(i);
        }
    }

    int corpse;
    int status;
    while ((corpse = wait(&status)) > 0)
        printf("%d: child %d exited with status 0x%.4X\n", getpid(), corpse, status);
    return 0;
}

样本输出:

$ ./test-forking
[PARENT] with pid 13904
[CHILD] with pid 13905 from parent with pid 13904
[CHILD] with pid 13906 from parent with pid 13904
[CHILD] with pid 13907 from parent with pid 13904
[CHILD] with pid 13908 from parent with pid 13904
[CHILD] with pid 13909 from parent with pid 13904
[CHILD] with pid 13905 exiting with status 2
13904: child 13905 exited with status 0x0200
[CHILD] with pid 13906 exiting with status 3
13904: child 13906 exited with status 0x0300
[CHILD] with pid 13907 exiting with status 4
13904: child 13907 exited with status 0x0400
[CHILD] with pid 13908 exiting with status 5
13904: child 13908 exited with status 0x0500
[CHILD] with pid 13909 exiting with status 6
13904: child 13909 exited with status 0x0600
$

对代码的升级也会在每行输出中打印时间。

2。杀戮

任何进程(在由父进程创建的集合中)都可以使用kill() 系统调用杀死它知道的任何其他进程(在集合中)。真的不清楚你是想让第一个孩子还是最后一个孩子杀死父母,或者别的什么。如果第一个孩子杀死了父母,第一个孩子将是唯一的孩子(因为延迟)。也不清楚为什么要在进程之间发送信号。

3。循环

是的,你可以做点什么——问题是,你真正追求的是什么。简单地多次打印parentchild 不需要多个进程。如果你想让父母说“我在这里”,每个孩子定期说“我在这里”,你需要让孩子循环和睡觉,在所有孩子都被创建后,父母循环和睡觉.不难做到。

【讨论】:

  • "任何进程可以杀死它所知道的使用kill()系统调用的任何其他进程。" ——乔纳森·莱弗勒的花絮。 ;)
  • @Seb:有什么问题? (我已将“The any”修复为“Any”。)如果其中一个进程知道集合中另一个进程的 PID,它可以通过kill() 发送信号。父母可以向任何孩子发送信号;任何孩子都可以向父母发送信号。孩子们之间很难互相发送信号,但如果系统像我一样空闲,他们可以猜测其他孩子的 PID。如果他们选择了与他们无关的 PID,则信号将失败,但讨论仅限于父进程创建的进程集(我会同意你可能更清楚)。
  • sleepingrunning 并不互斥,是吗?我想说所有存在的线程也在_running,无论是睡眠还是活动,因此,彼此并行运行。请解释你为什么说它们不平行。
  • @ryyker:在问题的原始代码中,第一个孩子在创建第二个孩子之前很久就退出了,这不是“并行运行”的任何有意义的“并行运行”定义我知道的。做到这一点并不需要太多,因此这些进程同时“运行”(至少,存在);正如我修改后的代码所示,让孩子们睡一觉就足够了。以我的经验,睡眠与运行不同,但进程并行存在,无论是睡眠还是运行——但不是一旦退出。未等待的进程当然会变成僵尸,直到等待。
  • 好。现在剩下的唯一问题是语法错误:“任何进程......它知道......”;你在谈论一组进程,就好像它是一个单一的一样。你在回复我时解释它的方式似乎在语法上是正确的。
【解决方案2】:

问题 3)。 ...我可以将 main 函数放入无限循环中...

当然可以

int  main(void)
{
    int c=0;
    while((c != 'q') && (c != EOF))//loops until c == q (and c!=EOF)
    {
        c = getchar();//waits until stdin sees a "q", (i.e. from keyboard)

        //An EOF (-1) or `q` will exit the loop
        //any other input will allow execution flow to continue, 1 loop at a time.  
        //Add additional forking code here.           
        //for each loop, spawn a new thread.
        //All secondary threads spawned will run parallel to other threads.
    }
    //exiting here will kill all threads (secondary and primary.)
    return 0;
}

【讨论】:

    【解决方案3】:

    1) 是的,你的父进程和子进程在 fork 之后是并行运行的, 您可以通过无限循环子进程并在父进程和其他进程执行相同操作时打印其名称来看到这一点。

    2) 是的,方法如下:

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <stdbool.h>
    #include <sys/types.h>
    #include <signal.h>
    
    int main()
    {
        pid_t pid;
        int i = 0;
    
        if ((pid = fork()) == 0)
        {
            if ((pid = getppid()) == -1)
            {
                fprintf(stderr, "child error: getppid()\n");
                exit(1);
            }
            if (kill(pid, 9) == -1)
            {
                fprintf(stderr, "child error: kill()\n");
                exit(1);
            }
    
            while (true)
            {
                printf ("child %d\n", ++i);
            }
        }
        else if (pid == -1)
        {
            fprintf(stderr, "error: fork()\n");
            return 1;
        }
    
        while (true)
        {
            printf("parent %d\n", ++i);
        }
    
        return 0;
    }
    

    3) 如果您需要该特定模式,则需要进程间通信和同步。建议this

    【讨论】:

    • 哈哈!一位用户来到 StackOverflow 寻求指导,我们应该将他们发送给 Google。谢谢你的启示。我很确定这不是投票鼓励的目的,但在我认为我可以让我的“以身作则”的事情上稍微下滑一点。 +1 让我发笑,先生。
    • @Nick 我发现 JonathanLeffler 的答案 - 建议更接近我的想法。也谢谢你的回复。
    猜你喜欢
    • 1970-01-01
    • 2015-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-29
    • 2011-09-06
    • 2012-01-04
    相关资源
    最近更新 更多