Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 计算N次幂和_C_Fork - Fatal编程技术网

C 计算N次幂和

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 <

此程序应计算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 <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的读取端