C 使用信号打印奇偶数
我需要打印自然编号1,2,…n,这样父进程打印所有奇数,子进程打印所有偶数,所有这些都需要使用POSIX信号来完成。我将如何着手实现这一点 输出应为: 家长:1C 使用信号打印奇偶数,c,signals,C,Signals,我需要打印自然编号1,2,…n,这样父进程打印所有奇数,子进程打印所有偶数,所有这些都需要使用POSIX信号来完成。我将如何着手实现这一点 输出应为: 家长:1 儿童:2 家长:3 …我认为给你布置这个家庭作业是为了让你尝试很多解决方案,并自己得出结论,信号不是一种好的同步技术 这是一个宝贵的教训,记住它,从现在开始使用信号量 如果你能提供到目前为止你所拥有的,并解释哪些不符合预期,可能会对你更为有利,但以下是我的想法: #include <stdio.h> #include <
儿童:2
家长:3
…我认为给你布置这个家庭作业是为了让你尝试很多解决方案,并自己得出结论,信号不是一种好的同步技术
这是一个宝贵的教训,记住它,从现在开始使用信号量 如果你能提供到目前为止你所拥有的,并解释哪些不符合预期,可能会对你更为有利,但以下是我的想法:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#define READY_SIGNAL SIGUSR1
/* The ready flag is set when READY_SIGNAL is received.
* It is needed so that when we wake up from sigsuspend
* we know whether or not the signal received was READY_SIGNAL. */
volatile sig_atomic_t ready;
void make_ready(int i) { ready = 1; }
int
main (int argc, char *argv[])
{
pid_t cpid, ppid; /* pids of the child and parent */
/* Signal masks for sigprocmask and sigsuspend */
sigset_t block_mask, wait_mask;
unsigned long c = 1; /* The counter */
unsigned long n = 100; /* The default max count value */
struct sigaction act;
/* Override the default max count if provided */
if (argv[1])
n = strtoul(argv[1], NULL, 10);
/* Prepare signal masks */
sigemptyset(&wait_mask);
sigemptyset(&block_mask);
sigaddset(&block_mask, READY_SIGNAL);
/* Set the signal mask for the parent to ignore READY_SIGNAL until
* we are ready to receive it, the mask will be inherited by the child,
* needed to avoid race conditions */
sigprocmask(SIG_BLOCK, &block_mask, NULL);
/* Register the signal handler, will be inherited by the child */
act.sa_flags = 0;
act.sa_handler = make_ready;
sigemptyset(&act.sa_mask);
sigaction(READY_SIGNAL, &act, NULL);
/* Get the parent's process id, needed for the child to send signals
* to the parent process, could alternatively use getppid in the child */
ppid = getpid();
/* Call fork, storing the child's process id needed for the parent to
* send signals to the child */
cpid = fork();
if (cpid < 0) {
perror("Fork failed");
exit(EXIT_FAILURE);
}
if (cpid == 0) {
/* Child */
c = 2; /* Child's first number will always be 2 */
if (c > n) exit(0); /* If c > n we have nothing to do */
do {
/* Suspend until we receive READY_SIGNAL */
while (!ready) sigsuspend(&wait_mask);
/* Print out number, flush for proper output sequencing when output
is not a terminal. */
printf("Child: %lu\n", c);
fflush(stdout);
ready = 0; /* Reset ready flag */
c += 2; /* Increment counter */
/* Wake up parent process */
kill(ppid, READY_SIGNAL);
} while (c <= n);
} else {
/* Parent */
for (;;) {
/* Print out number, flush for proper output sequencing when output
is not a terminal. */
printf("Parent: %lu\n", c);
fflush(stdout);
c += 2; /* Increment counter */
kill(cpid, READY_SIGNAL); /* Wake up child process */
if (c > n) break; /* Don't go back to sleep if we are done */
ready = 0; /* Reset ready flag */
/* Suspend until we receive READY_SIGNAL */
while (!ready) sigsuspend(&wait_mask);
};
wait4(cpid, NULL, 0); /* Don't exist before child finishes */
}
return 0;
}
#包括
#包括
#包括
#包括
#包括
#定义就绪信号SIGUSR1
/*当收到ready_信号时,设置ready标志。
*这是必要的,这样当我们从梦中醒来时
*我们知道接收到的信号是否为就绪信号*/
挥发性sig_原子_t ready;
void make_ready(inti){ready=1;}
int
main(int argc,char*argv[])
{
pid_t cpid,ppid;/*子项和父项的pid*/
/*sigprocmask和sigsuspend的信号掩码*/
sigset\u t块\u掩码,等待\u掩码;
无符号长c=1;/*计数器*/
无符号长n=100;/*默认最大计数值*/
结构动作法;
/*覆盖默认的最大计数(如果提供)*/
if(argv[1])
n=strtoul(argv[1],NULL,10);
/*准备信号屏蔽*/
SIGEPTYSET(&wait_掩码);
SIGEPTYSET(和块屏蔽);
sigaddset(块屏蔽,就绪信号);
/*将父级的信号掩码设置为忽略就绪\u信号,直到
*我们已经准备好接受它,面具将被孩子继承,
*需要避免比赛条件*/
SIGPROCSMASK(SIG_块和块_块掩码,NULL);
/*注册信号处理程序,将由子级继承*/
act.sa_标志=0;
act.sa_handler=准备就绪;
sigemptyset(和act.sa_面具);
sigaction(准备就绪信号和动作,空);
/*获取子进程发送信号所需的父进程id
*对于父进程,也可以在子进程中使用getppid*/
ppid=getpid();
/*调用fork,存储父进程调用所需的子进程id
*给孩子发信号*/
cpid=fork();
如果(cpid<0){
perror(“Fork失败”);
退出(退出失败);
}
如果(cpid==0){
/*孩子*/
c=2;/*孩子的第一个数字总是2*/
如果(c>n)退出(0);/*如果c>n,我们无事可做*/
做{
/*暂停,直到我们收到就绪信号*/
while(!ready)sigsupspend(&wait_mask);
/*打印输出编号,输出时刷新以正确的输出顺序
不是终点站*/
printf(“子项:%lu\n”,c);
fflush(stdout);
就绪=0;/*重置就绪标志*/
c+=2;/*增量计数器*/
/*唤醒父进程*/
终止(ppid,准备就绪信号);
}休息时;/*如果我们做完了,就不要再睡觉*/
就绪=0;/*重置就绪标志*/
/*暂停,直到我们收到就绪信号*/
while(!ready)sigsupspend(&wait_mask);
};
wait4(cpid,NULL,0);/*在子级完成之前不存在*/
}
返回0;
}
这通过了以下基本测试:
/print\u带有100000个信号| sort-n-k2-c&&echo“Success”
/print\u带有信号100001 | sort-n-k2-c和echo“Success”