C 计算N次幂和
此程序应计算2^1+2^2+…+的值2^10:C 计算N次幂和,c,fork,C,Fork,此程序应计算2^1+2^2+…+的值2^10: #include <stdio.h> #include <string.h> #include <stdlib.h> #include <assert.h> #include <stdbool.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> #include <
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <math.h>
#define N 10
// sommatoria per i che va da 1 a N di 2^i, ogni processo calcola un singolo valore
int main(int argc, char** argv)
{
pid_t figli[N];
unsigned int i;
int status;
int fd[N][2];
int msg1=0,msg2;
int risultato=0;
bool padre=true;
for(i=0;i<N && padre;i++)
{
pipe(fd[i]);
figli[i]=fork();
if(figli[i]<0)
{
fprintf(stderr,"Una fork ha fallito\n");
}
else if(figli[i]==0)
{
padre=false;
}
else
{
msg1=i+1;
write(fd[i][1],&msg1,sizeof(int));
}
}
if(!padre)
{
read(fd[i][0],&msg2,sizeof(int));
msg2=pow(2.0,msg2);
write(fd[i][1],&msg2,sizeof(int));
exit(0);
}
else
{
for(i=0;i<N;i++)
{
read(fd[i][0],&msg2,sizeof(int));
risultato+=msg2;
}
}
if(padre)
fprintf(stderr,"%d\n",risultato);
return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义n10
//在瓦洛尔河沿岸的ogni过程中,每个人都会有一个梦游症
int main(int argc,字符**argv)
{
pid_t figli[N];
无符号整数i;
智力状态;
int fd[N][2];
int msg1=0,msg2;
int-risultato=0;
bool-padre=true;
对于(i=0;i而言,上述代码的问题在于,同一管道用于同一进程的写入和读取(这里是父进程)
父函数将要计算的值传递给使用管道的子。子写在同一个管道中。父读回ANS。这里,您没有考虑情况:父向管道写入值,并读取回复本身。因此,孩子从未得到该值。
要解决上述问题,必须创建两个管道:
从父级到子级的管道
从子级到父级的管道
这将防止出现不同的竞争条件,代码的可读性也将大大提高。
下面是执行相同操作的代码。
PS:因为这可能是一个家庭作业,我不是给你确切的解决方案,而是给你一个问题的想法。下次,请使用英语作为命名方案。这有助于人们调试你的代码
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(void)
{
int msg;
int child_pid;
int parent_to_child[2];
int child_to_parent[2];
// my_pipe
int ret_val = pipe(parent_to_child);
if(ret_val!=0){
printf("pipe command failed !!\n");
exit(1);
}
// my_lock
ret_val = pipe(child_to_parent);
if(ret_val!=0){
printf("pipe command failed !!\n");
exit(1);
}
child_pid = fork();
if(child_pid==-1){
printf("fork() failed !!\n");
exit(1);
}else if(child_pid==0){
// i am child
read(parent_to_child[0], &msg, sizeof(int));
printf("child got %d from parent \n", msg);
msg = 34;
write(child_to_parent[1], &msg, sizeof(int));
}else{
// i am parent
msg = 24;
write(parent_to_child[1], &msg, sizeof(int));
//sleep(2);
read(child_to_parent[0], &msg, sizeof(int));
printf("parent got %d from child \n", msg);
}
return 0;
}
#包括
#包括
#包括
内部主(空)
{
int-msg;
int-child_-pid;
int parent_to_child[2];
int child_to_parent[2];
//我的烟斗
int ret_val=管道(父管道到子管道);
如果(返回值!=0){
printf(“管道命令失败!!\n”);
出口(1);
}
//我的锁
ret_val=管道(子管道到父管道);
如果(返回值!=0){
printf(“管道命令失败!!\n”);
出口(1);
}
child_pid=fork();
如果(子项pid==-1){
printf(“fork()失败!!\n”);
出口(1);
}else if(子项pid==0){
//我是个孩子
读取(父对象到子对象[0],&msg,sizeof(int));
printf(“子项从父项获得%d”,msg);
msg=34;
写入(子对象到父对象[1],&msg,sizeof(int));
}否则{
//我是父母
msg=24;
写入(父对象到子对象[1],&msg,sizeof(int));
//睡眠(2);
读取(子对象到父对象[0],&msg,sizeof(int));
printf(“父对象从子对象\n获得%d”,msg);
}
返回0;
}
上述代码的问题是,同一个进程使用同一个管道进行写入和读取(这里是父进程)
父函数将要计算的值传递给使用管道的子。子写在同一个管道中。父读回ANS。这里,您没有考虑情况:父向管道写入值,并读取回复本身。因此,孩子从未得到该值。
要解决上述问题,必须创建两个管道:
从父级到子级的管道
从子级到父级的管道
这将防止出现不同的竞争条件,代码的可读性也将大大提高。
下面是执行相同操作的代码。
PS:因为这可能是一个家庭作业,我不是给你确切的解决方案,而是给你一个问题的想法。下次,请使用英语作为命名方案。这有助于人们调试你的代码
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(void)
{
int msg;
int child_pid;
int parent_to_child[2];
int child_to_parent[2];
// my_pipe
int ret_val = pipe(parent_to_child);
if(ret_val!=0){
printf("pipe command failed !!\n");
exit(1);
}
// my_lock
ret_val = pipe(child_to_parent);
if(ret_val!=0){
printf("pipe command failed !!\n");
exit(1);
}
child_pid = fork();
if(child_pid==-1){
printf("fork() failed !!\n");
exit(1);
}else if(child_pid==0){
// i am child
read(parent_to_child[0], &msg, sizeof(int));
printf("child got %d from parent \n", msg);
msg = 34;
write(child_to_parent[1], &msg, sizeof(int));
}else{
// i am parent
msg = 24;
write(parent_to_child[1], &msg, sizeof(int));
//sleep(2);
read(child_to_parent[0], &msg, sizeof(int));
printf("parent got %d from child \n", msg);
}
return 0;
}
#包括
#包括
#包括
内部主(空)
{
int-msg;
int-child_-pid;
int parent_to_child[2];
int child_to_parent[2];
//我的烟斗
int ret_val=管道(父管道到子管道);
如果(返回值!=0){
printf(“管道命令失败!!\n”);
出口(1);
}
//我的锁
ret_val=管道(子管道到父管道);
如果(返回值!=0){
printf(“管道命令失败!!\n”);
出口(1);
}
child_pid=fork();
如果(子项pid==-1){
printf(“fork()失败!!\n”);
出口(1);
}else if(子项pid==0){
//我是个孩子
读取(父对象到子对象[0],&msg,sizeof(int));
printf(“子项从父项获得%d”,msg);
msg=34;
写入(子对象到父对象[1],&msg,sizeof(int));
}否则{
//我是父母
msg=24;
写入(父对象到子对象[1],&msg,sizeof(int));
//睡眠(2);
读取(子对象到父对象[0],&msg,sizeof(int));
printf(“父对象从子对象\n获得%d”,msg);
}
返回0;
}
有趣的是,55是从1到10的所有数字的总和:这应该给你一个即时线索:
pipe()创建一个管道,一个可用于进程间通信的单向数据通道。数组pipefd用于返回两个文件描述符,表示管道的端点。pipefd[0]表示管道的读取端。pipefd[1]表示管道的写入端
请注意:单向。换句话说,padre正在读回它所写的相同值(因此为55)
你通常为双向交通设置两条管道,每个方向一条。所以我把管道的数量增加了一倍,牧师对孩子使用偶数管道,另一个方向使用奇数管道
此外,您的孩子继续使用padre循环,而他们应该立即退出该循环,这样他们的i
值是正确的。您确实有基于padre
的循环退出,但这是在i
发生更改后发生的。您可以在将padre
设置为false的位置中断,也可以在if(!padre)
位用于将i
还原到此子项的正确值。我已完成后者
以下代码(带有显示更改内容的标记)正常工作:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <math.h>
#define N 10
int main(int argc, char** argv)
{
pid_t figli[N];
unsigned int i;
int status;
int fd[N*2][2]; // CHANGED: two unidirectional pipes
int msg1=0,msg2;
int risultato=0;
bool padre=true;
for(i=0;i<N && padre;i++)
{
pipe(fd[i*2]);
pipe(fd[i*2+1]); // ADDED: create second pipe
figli[i]=fork();
if(figli[i]<0)
{
fprintf(stderr,"Una fork ha fallito\n");
}
else if(figli[i]==0)
{
padre=false;
}
else
{
msg1=i+1;
write(fd[i*2][1],&msg1,sizeof(int)); // CHANGED: pipe number
}
}
if(!padre)
{
i--; // ADDED: to restore i for the child
read(fd[i*2][0],&msg2,sizeof(int)); // CHANGED: pipe number
msg2=pow(2.0,msg2);
write(fd[i*2+1][1],&msg2,sizeof(int)); // CHANGED: pipe number
exit(0);
}
else
{
for(i=0;i<N;i++)
{
read(fd[i*2+1][0],&msg2,sizeof(int)); // CHANGED: pipe number
risultato+=msg2;
}
}
if(padre)
fprintf(stderr,"%d\n",risultato);
return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义n10
int main(int argc,字符**argv)
{
pid_t figli[N];
无符号整数i;
智力状态;
int fd[N*2][2];//更改:两个单向管道
int msg1=0,msg2;
int-risultato=0;
bool-padre=true;
(i=0;i有趣的是,55是从1到10的所有数字的总和:这应该给你一个即时线索:
pipe()创建一个管道,一个可用于进程间通信的单向数据通道。数组pipefd用于返回两个文件描述符,它们表示管道的末端。pipefd[0]表示t的读取端