gpt4 book ai didi

c - 使用信号在父进程和多个子进程之间进行进程同步

转载 作者:太空宇宙 更新时间:2023-11-04 10:37:55 24 4
gpt4 key购买 nike

我正在学习如何在 Linux 中使用信号。有 4 个子进程和 1 个父进程。我的输出应该在这些阶段进行:

parent 收到 child 1的信号

parent 收到 child 2的信号

父级接收到子级 3 的信号

parent 收到 child 4的信号

初始化结束

第一阶段开始

child 1 收到来自 parent 的信号

child 2 收到来自 parent 的信号

child 3 收到来自 parent 的信号

child 4 收到来自 parent 的信号

parent 收到 child 1的信号

parent 收到 child 2的信号

父级接收到子级 3 的信号

parent 收到 child 4的信号

第一阶段结束

第 2 阶段开始

child 1 收到来自 parent 的信号

child 2 收到来自 parent 的信号

child 3 收到来自 parent 的信号

child 4 收到来自 parent 的信号

我目前正在尝试在第 1 阶段结束之前完成该部分,但我很挣扎。这是我的代码:

#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#define MAXCP 3
int ccount=0;
void p_action(int sig){
if (sig == SIGUSR2){
printf("\ncontroller(%d): Received signal SIGUSR2 from child process\n",
(int)getpid());
}
--ccount;
}

void c_action(int sig){
if (sig == SIGUSR1){
printf("\ncompute(%d): Received signal SIGUSR1 from parent process %d\n",
(int)getpid(), (int)getppid());
}
exit(0);
}

int main(){

pid_t pid[MAXCP], parent_pid;
//int nprocs = 0;
ccount = MAXCP;

static struct sigaction pact, cact[MAXCP];

pact.sa_handler = p_action;
sigaction(SIGUSR2, &pact, NULL);


int count;
for (count = 0; count < MAXCP; count++){
switch(pid[count] = fork()){
case -1:
perror("Fork error");
exit(1);
case 0:
//sleep(1);
cact[count].sa_handler = c_action;
sigaction(SIGUSR1, &cact[count], NULL);
printf("Sending SIGUSR2 to parent");
kill(getppid(), SIGUSR2);
pause();
break;
default:
pause();
//printf("Parent is sleeping");

while (ccount != MAXCP){
sleep(60);
}
for (ccount = 0; ccount < MAXCP; ccount++)
kill(pid[count], SIGUSR1);
break;

}
}


return 0;
}

我的输出是这样的:

// When I use the above code
controller(3132): Received signal SIGUSR2 from child process
// When I comment out the pause in the child section
controller(3140): Received signal SIGUSR2 from child process
Sending SIGUSR2 to parent
controller(3141): Received signal SIGUSR2 from child process
Sending SIGUSR2 to parentSending SIGUSR2 to parentSending SIGUSR2 to parentSending SIGUSR2 to parentSending SIGUSR2 to parent
controller(3142): Received signal SIGUSR2 from child process
^C

感谢您的宝贵时间。

最佳答案

您想要使用信号的目的与它们的设计目的并非 100% 匹配。最重要的问题是信号充当硬件中断 Controller 。如果相同值的多个信号“同时”发生,它们在接收器中看起来将合并为一个信号。在下面的例子中,我们通过对每个 child 使用不同值的 sleep 来解决这个问题。

因此,当内核重新安排进程时,它只是检查自上次进程处于事件状态以来是否收到了每个信号,并在需要时将它们转发到进程中。它不知道发生了多少次。

#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#define MAXCP 3
volatile int ccount=0;
void p_action(int sig, siginfo_t *info, void *ptr){
if (sig == SIGUSR2){
printf("\ncontroller(%d): Received signal SIGUSR2 from child %d process\n",
(int)getpid(), (int)info->si_pid);
}
--ccount;
}

void c_action(int sig){
if (sig == SIGUSR1){
printf("\ncompute(%d): Received signal SIGUSR1 from parent process %d\n",
(int)getpid(), (int)getppid());
}
}

int main(){
int count;
pid_t pid[MAXCP];
ccount = MAXCP;

struct sigaction pact;

pact.sa_flags = SA_SIGINFO | SA_RESTART; /* if signal comes on top of each other, we need this */
pact.sa_sigaction = p_action;
sigaction(SIGUSR2, &pact, NULL);

/* spawdn children */
for (count = 0; count < MAXCP; count++){
switch(pid[count] = fork()){
case -1:
perror("Fork error");
exit(1);
case 0:
{
struct sigaction cact;
cact.sa_flags = 0;
cact.sa_handler = c_action;
sigaction(SIGUSR1, &cact, NULL);
pause();
sleep(1);
printf("Sending SIGUSR2 to parent (%d)\n", getppid());
sleep(count+1);
kill(getppid(), SIGUSR2);
exit(0);
break;
}
default:
break;
}
}

sleep (1); /* let children have time to configure sigaction() */

/* notify all children */
for (count = 0; count < MAXCP; count++){
printf ("Sending SIGUSR1 to child %d\n", (int)pid[count]);
kill(pid[count], SIGUSR1);
}

/* wait for children to notify back */
while (ccount)
{
usleep(10000); /* else CPU throttles */
}

for (count = 0; count < MAXCP; count++){
int status;
waitpid (pid[count], &status, 0);
printf ("Child process %d reaped. status=%d\n", pid[count], status);
kill(pid[count], SIGUSR1);
}

return 0;
}

图像内核对每个进程都有一个记录,说明它在休眠时收到了哪些信号。

struct Process
{
bool hasReceivedSIGINT;
bool hasReceivedSIGUSR1;
bool hasReceivedSIGUSR2;
bool hasReceivedSIGUSR3;
};

信号用于“插入”其他进程。一个很好的例子是使进程重新加载配置文件。对于 IPC 通信,pipe() 是更好的方法。

关于c - 使用信号在父进程和多个子进程之间进行进程同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36532016/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com