我正在学习如何在linux中使用信号。有4个子进程和一个父进程。我的输出应该在这些阶段进行:
家长收到来自孩子1的信号
家长收到来自孩子2的信号
家长收到来自孩子3的信号
家长收到来自孩子4的信号
初始结束
第1阶段开始
儿童1收到来自父母的信号
儿童2收到来自父母的信号
儿童3收到来自父母的信号
儿童4接收来自父母的信号
家长收到来自孩子1的信号
家长收到来自孩子2的信号
家长收到来自孩子3的信号
家长收到来自孩子4的信号
阶段1结束
第2阶段开始
儿童1收到来自父母的信号
儿童2收到来自父母的信号
儿童3收到来自父母的信号
儿童4接收来自父母的信号
我目前正试图在第一阶段结束之前做这个部分而且我正在努力。这是我的代码:
#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
感谢您的时间。
答案 0 :(得分:1)
您想要使用信号的内容与其设计目标不完全匹配。最重要的问题是信号充当硬件中断控制器。如果同一值的多个信号同时发生&#34;同时#34;它们将看起来合并为接收器中的一个信号。在下面的示例中,我们通过在每个孩子中使用具有不同值的睡眠来解决这个问题。
因此,当内核重新安排进程时,它只检查自上次进程激活后是否已收到每个信号,并在需要时将它们转发到进程中。它不知道发生了多少次。
#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;
};
信号用于&#34;轻推&#34;其他过程。一个很好的例子是创建一个进程重新加载配置文件。对于IPC通信,pipe()是一种更好的方法。