并非我的所有子进程都运行在 for 循环的末尾

如何解决并非我的所有子进程都运行在 for 循环的末尾

我有一个项目,我需要在其中创建 N 个子进程并在它们之间进行选举。所以到目前为止我已经做了一个函数来生成随机数(对于选举,他们必须比较他们被赋予的数字,然后选出较低的数字)。然后,我坚持让他们与管道通信以比较数字。我的问题是只有我的第一个子进程运行这个 for 循环的结尾我真的不明白为什么。到目前为止,这是我的所有代码:

void comparerIdElection(int (*pipes)[2],int numProc)
{


for (int i = 0; i < NBPROC; ++i)
    {
    if (numProc!=i)
    {
        close(pipes[i][0]);
        printf("je suis %d et je ferme la pipe [%d][0]\n",getpid(),i );
    }else printf("je suis %d et je laisse la pipe [%d][0] \n",i );
    if (numProc +1 != i)
    {
        close(pipes[i][1]);
        printf("je suis %d et je ferme la pipe [%d][1]\n",i );
    }else printf("je suis %d et je laisse la pipe [%d][1] \n",i );
}


//Generate a random number for my child process
int GenererIdElection ()
{
    srand(time(NULL)^getpid()<<16);
    return rand()%NBPROC;
}






   int main(int argc,char const *argv[])
{
    int N = NBPROC,idElection,numProc= -1; 
    int pere = getpid();
/*Creation du nombre de pipe adequat */
    int pipes[N][2];
    int pids[N];
/* Indique l'etat du processus C = Candidat,B =B battu,E = Elu*/
    char etat ; 
    printf("le nombre de processus que je crée est : %d\n",N);


// Creation d'un nombre de N processus fils par le même pere
    for (int i = 0; i < N; ++i)
    {
            if(getpid()==pere){
                fork() ; 
                numProc ++ ;
            }       
    }

    if (getpid() != pere)
    {
        pids[numProc] = getpid();
        etat = 'C';
        while(etat == 67)
        {
            idElection = GenererIdElection();
            printf("je suis %d et j'ai eu %d,mon num proc est %d \n",numProc);
            comparerIdElection(pipes,numProc);
            printf("hop\n");
            etat ='B';
            
        }

    }


    if (getpid()==pere)
    {
    /*On attend la fin de chaque processus
     pour mettre un terme au processu pere*/
        for (int i = 0; i < N; ++i)
        {
            wait(&pids[i]);
        }
    }
    exit(0);
}

这是执行后会发生的情况(我翻译了所有 printf):

[终端][1]

编辑:由于缺乏声誉,我无法发布图片,因此我复制/面食:

我是 1854 我有 1,我的 numproc 是:0
我是 1854 我不关闭管道 [0][0]
我是 1854 我关闭 [0][1]
我是 1854 我关闭管道 [1][0]
我是 1854 我不关闭管道 [1][1]
我是 1854 我关闭管道 [2][0]
我是 1854 我关闭 [2][1]

我是 1855 我有 1,我的 numproc 是:1
我是 1855 我关闭管道 [0][0]
我是 1855 我关闭 [0][1]
我是 1855 我不关闭管道 [1][0]
我是 1856 我有 1,我的 numproc 是:2
我是 1856 我关闭管道 [0][0]
我是 1856 我关闭 [0][1]
我是 1856 我关闭管道 [1][0]

NB : NBPROC = 3 在这种情况下,但不管数值是多少,除了第一个子进程外,它不起作用。

解决方法

我似乎对你的程序的行为有一个合理的解释。正如我在评论中已经指出的那样,程序中存在一个明显的缺陷,即未设置 int pipes[N][2]; 最终会出现在 close() API 中,实际上只是导致 {{1 }} 被退回,可能没有达到预期的效果。

至于程序的行为,可以通过检查数组 EBADF 中填充的实际值来解释。由于原始问题中没有明确设置这些值,因此这些值基本上是未定义的,但是...

让我们尝试使用以下方法将它们设置为更合理的值:

int pipes[N][2];

传入 0 产生输出:

int pipeVal = INT32_MIN;
if(argc == 2) {
    pipeVal = atoi(argv[1]);
}
for(int i = 0; i < N; ++i) {
    if(pipeVal != INT32_MIN) {
        pipes[i][0] =  pipes[i][1] = pipeVal;
    }
    printf("%d: Pipe pair %d-%d\n",getpid(),pipes[i][0],pipes[i][1]);
}

这似乎符合预期:fork 3 个最终会退出的进程。让我们用 1 的值试试

61962: Number of process is : 3
61962: Pipe pair 0-0
61962: Pipe pair 0-0
61962: Pipe pair 0-0
61963: Election Id 0,numProc 0 
61963: Exiting while-loop
61964: Election Id 0,numProc 1 
61964: Exiting while-loop
61965: Election Id 0,numProc 2 
61965: Exiting while-loop

现在这看起来很奇怪,因为没有一个进程真正退出 while 循环,但主程序成功终止。为了实际检查子程序的退出状态,我添加了以下代码:

62033: Number of process is : 3
62033: Pipe pair 1-1
62033: Pipe pair 1-1
62033: Pipe pair 1-1
62034: Election Id 0,numProc 0 
62035: Election Id 2,numProc 1 
62036: Election Id 0,numProc 2 

这是传入 1 作为参数的输出:

if (getpid()==pere)
{
/*On attend la fin de chaque processus
 pour mettre un terme au processu pere*/
    for (int i = 0; i < N; ++i)
    {
        errno = 0;
        int stat_val;
        wait(&stat_val);
        #if DBG == 1
        printf("%d: WIFEXITED(%d),WEXITSTATUS(%d),WIFSIGNALED(%d),WTERMSIG(%d),WIFSTOPPED(%d),WSTOPSIG(%d),WIFCONTINUED(%d)\n",WIFEXITED(stat_val),WEXITSTATUS(stat_val),WIFSIGNALED(stat_val),WTERMSIG(stat_val),WIFSTOPPED(stat_val),WSTOPSIG(stat_val),WIFCONTINUED(stat_val));
        #endif
    }
}

这个输出表明所有进程正常退出,没有被任何信号异常停止。

线索就在这些进程试图关闭的实际 62215: WIFEXITED(1),WEXITSTATUS(0),WIFSIGNALED(0),WTERMSIG(0),WIFSTOPPED(0),WSTOPSIG(0),WIFCONTINUED(0) 62215: WIFEXITED(1),WIFCONTINUED(0) 中。在 Linux 中(至少)一个进程一旦创建就有 3 个文件描述符,fd0stdin1stdout2 .当 0 作为参数传递给程序时,进程最终会关闭无论如何都没有使用的 stderr (stdin),因此没有问题,它们退出 close(0) 并随后的while循环。当 1 作为参数传递给程序时,进程最终关闭 comparerIdElection() (stdout),因此任何应该写入输出的内容都不再出现在控制台上,但是它们仍然退出 close(1) 和随后的 while 循环,从而从每个进程中退出 comparerIdElection()

现在来到共享的实际程序,最终填充的实际值是什么是未指定的,但是如果即使数组中的 WIFEXITED(1) N*2 之一设置为 1,应展示上述行为(传入 1),即,即使 fd 不会写入控制台,但进程确实退出了 while 循环并且主父进程能够成功等待过程。在我的 PC 上(我也怀疑在您的 PC 上),这些数组元素中至少一个的实际值始终设置为 1。

我的 Mac 上管道 fd 对的值:

printf

他们在 TryItOnline 上的价值:

61120: Pipe pair -296602944-32766
61120: Pipe pair 23978080-1
61120: Pipe pair 64-0

它们在 OnlineGDB 上的值(需要添加编译器标志 25090: Pipe pair 0-0 25090: Pipe pair 68079952-32708 25090: Pipe pair 1-0 ):

-DNBPROC=3

无论 5612: Pipe pair 1505064448-32611 5612: Pipe pair 1507242440-32611 5612: Pipe pair 1-0 的值如何,此分析都应成立,因为在管道 NBPROC 中存在 1 之前,该进程将最终关闭自己的 fd 并表现出类似的行为。

这是一个完整的程序,其中包含一些可以通过传入 stdout 和一些 PID 标记来启用的检测,以确定哪个进程是来自 :

DBG=1

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res