C 叉子上的打印错误
我为我的英语道歉,希望你能理解。 因此,我的程序中有一个printf的问题,它在父亲结束时等待,在printf之前等待。所以我总是让父亲打印他的所有信息,然后儿子打印他的所有信息,而信息应该被划掉 从我所看到的,我读到,我必须有一个flush,但它不能解决我的问题。 谢谢你的帮助。 这是我的密码C 叉子上的打印错误,c,linux,printf,fork,semaphore,C,Linux,Printf,Fork,Semaphore,我为我的英语道歉,希望你能理解。 因此,我的程序中有一个printf的问题,它在父亲结束时等待,在printf之前等待。所以我总是让父亲打印他的所有信息,然后儿子打印他的所有信息,而信息应该被划掉 从我所看到的,我读到,我必须有一个flush,但它不能解决我的问题。 谢谢你的帮助。 这是我的密码 #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/wait
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#include <unistd.h>
#include <sys/shm.h>
int cpt = 0;
void fils(int *cpt){
int i;
for(i = 0; i < 3; i++){
(*cpt)++;
printf("son : %d\n", *cpt);
}
}
void pere(int *cpt){
int i;
for(i = 0; i < 3; i++){
(*cpt)--;
printf("father : %d\n", *cpt);
fflush(stdout);
}
}
int main (int argc, char*argv[]){
key_t key;
int memShared;
int *cpt = NULL;
key = ftok(argv[0],'p');
memShared = shmget(key, sizeof(int), IPC_CREAT|IPC_EXCL|0666);
cpt = shmat ( memShared, cpt, 0);
*cpt = 0;
fflush(stdout);
switch (fork()){
case -1: perror("erreur de création du fils");
exit(99);
case 0: fils(cpt);
exit(1);
default: pere(cpt);
wait(NULL);
}
shmctl(memShared, IPC_RMID, NULL);
return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
int-cpt=0;
无效文件(内部*cpt){
int i;
对于(i=0;i<3;i++){
(*cpt)++;
printf(“子:%d\n”,*cpt);
}
}
无效pere(整数*cpt){
int i;
对于(i=0;i<3;i++){
(*cpt)--;
printf(“父亲:%d\n”,*cpt);
fflush(stdout);
}
}
int main(int argc,char*argv[]){
钥匙(t)钥匙;;
int memShared;
int*cpt=NULL;
key=ftok(argv[0],'p');
memShared=shmget(键,sizeof(int),IPC|u CREAT | IPC|u EXCL | 0666);
cpt=shmat(memShared,cpt,0);
*cpt=0;
fflush(stdout);
开关(fork()){
案例1:perror(“法院的审查”);
出口(99);
案例0:fils(cpt);
出口(1);
默认值:pere(cpt);
等待(空);
}
shmctl(memShared,IPC_RMID,NULL);
返回0;
}
我总是把这个放在候机楼里
父亲:-1
父亲:-1
父亲:-2
儿子:0
儿子:-1
儿子:0
我认为它应该被划掉例如父亲:-1儿子:0父亲:-1。。。
谢谢你的帮助。这是一场经典的比赛。要实现“儿子优先”顺序,只需在
开关中重新排列您的行即可:
switch (fork()){
case -1: perror("erreur de création du fils");
exit(99);
case 0: fils(cpt);
exit(1);
default: wait(NULL); //First - wait
pere(cpt); //Then - print
}
您无法保证这种简单的解决方案是否会如您所愿工作。您想要的是确保流程只执行一个循环迭代,直到它被关闭
如果您想确保它们以这种abababab
方式运行,那么您需要另一种同步机制。请记住,简单的信号量是不够的。您可能需要一个管道或fifo队列来允许此进程通信。查找名为pipe
或mkfifo
的函数。然后你可以这样做:
for(number_of_iterations)
{
wait for a message from the other process;
do work on shm;
send message to another process, allowing it to continue;
}
这将激发一种代币的概念
至于评论中的建议:将fork结果保留在变量a中,然后使用waitpid
等待,当您有更多进程时会更安全,因为wait
等待第一个结束的进程,而不是特定的进程
chenchongyf1@chenchongyf1:~$
chenchongyf1@chenchongyf1:~$ ./wrong_printf
father : -1
son : 0
son : 1
son : 2
father : 1
father : 0
chenchongyf1@chenchongyf1:~$**
这个程序在我的电脑上运行。我的意思是,父亲的printf和儿子的printf确实是交叉的。你说“应该交叉”,但你没有实现任何机制来做到这一点。两个进程都在竞相写入它们的所有输出,程序中没有任何东西让一个进程等待另一个进程。如果您想让他们交替输出,您必须编写代码让他们这样做。您也没有同步对共享内存的访问,这就是为什么您会得到奇怪的输出,就像父亲在一行中写入两个-1
一样。您始终需要将fork
的结果保存在一个变量中,因为父亲需要它来执行waitpid
。另请参见和@BasileStarynkevitch:不必要。他正在等待任何一个子进程完成。这已经足够有选择性了。(我们不是在一般情况下,我们真的需要使用waitpid
)@PaulGriffiths:嗨,谢谢你的回答。当我说“交叉”时,我的意思是我们永远不知道父亲或儿子中的哪一个会先运行,所以我认为父亲或儿子可以运行2次迭代和printf,然后儿子可以运行1次迭代,这样我们就可以得到交叉。这就是我说的候补人选。但是是的,你是对的,我忘了同步对共享内存的访问,我现在就纠正它!我已经更新了我的答案,以便更准确地回答你的问题。没关系。该程序可能有效,但不能保证有效。这通常是比赛中的一个问题。