Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/32.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管道写入/读取双工序列失败_C_Pipe_Ipc - Fatal编程技术网

C管道写入/读取双工序列失败

C管道写入/读取双工序列失败,c,pipe,ipc,C,Pipe,Ipc,对于这个C项目,我试图使用一个管道来获得一个父进程,以便与子进程通信。子级应该从txt文件(包含实数)中读取行(每秒一行),并使用管道提供父级,然后父级应该从管道中读取并将数字写入日志文件。但是,父进程只读取0.000000的序列。这是我的密码: #include <stdlib.h> #include <unistd.h> #include <ctype.h> #include <string.h> #include <time.h>

对于这个C项目,我试图使用一个管道来获得一个父进程,以便与子进程通信。子级应该从txt文件(包含实数)中读取行(每秒一行),并使用管道提供父级,然后父级应该从管道中读取并将数字写入日志文件。但是,父进程只读取0.000000的序列。这是我的密码:

#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <string.h>
#include <time.h>
#include <wait.h>
#define MAX_I 5
#define delay 1
void read_input(FILE *fp);

FILE *file_log;
int status;
pid_t pid;
int pipeFD[2];

int main(int argc, char **argv) {
//initialize
    FILE *fp;

    if (argc != 2){
    if ((fp = fopen("input.txt", "r")) == NULL) {
        printf("Error! opening file");
        exit(1);}
    }
    else{
        fp = fopen(argv[1], "r");
        }

    if (pipe(pipeFD) == -1){    /* creates a pipe */
    fprintf(stderr, "\nERROR: pipe() failed\n");
    exit(1);}

    file_log=fopen("file.log","w+"); /*open the log file*/

    pid=fork();
    if(pid==0) {//child process
    printf ("%d starts \n", getpid());
    close(pipeFD[0]);//close read end for child
    read_input(fp);
    return 0;
    exit(status);
    }else{//parent 
    double speed_read;
    close(pipeFD[1]);//close write end for parent
    while(1){
        if (read(pipeFD[0], &speed_read, sizeof(speed_read)) >0){
        if (speed_read<0)
        break;
        fprintf(file_log, "%f \n", speed_read); 
        printf("process %d received %f from child \n",getpid(),speed_read);
        }else
            printf("Nothing there to read \n");  
        }
    printf("parent ended \n");
    wait(&status);
    fclose(fp);
    fclose(file_log);
    }
    return 0;
}

void read_input(FILE *fp){
    char *line = NULL;
    double speed;
    int i=0; size_t len = 0; double exit_sign =-10.0;
    while(getline(&line, &len, fp) != -1) { 
        speed=atof(line);
        i++;
        if(i>MAX_I){//reads up to MAX_I rows of input
                        printf("I'll send the exit sign to parent now\n");
                        write(pipeFD[1], &exit_sign, sizeof(double));
                        free(line);
                        break;      
                    }
        if(write(pipeFD[1], &speed, sizeof(double)>0)){
            printf("%d at %d wrote that speed is %f\n",getpid(), i,speed);
        }else{printf("Write on pipe failed\n");}
        sleep(delay);
        }
    free(line);
}
#包括
#包括
#包括
#包括
#包括
#包括
#定义MAX_I 5
#定义延迟1
无效读取输入(文件*fp);
文件*文件日志;
智力状态;
pid_t pid;
int-pipeFD[2];
int main(int argc,字符**argv){
//初始化
文件*fp;
如果(argc!=2){
if((fp=fopen(“input.txt”,“r”))==NULL){
printf(“错误!打开文件”);
退出(1);}
}
否则{
fp=fopen(argv[1],“r”);
}
如果(管道(pipeFD)=-1){/*创建管道*/
fprintf(stderr,“\n错误:管道()失败\n”);
退出(1);}
file_log=fopen(“file.log”,“w+”)/*打开日志文件*/
pid=fork();
如果(pid==0){//子进程
printf(“%d开始\n”,getpid());
关闭(pipeFD[0]);//关闭子级的读取端
读取输入(fp);
返回0;
退出(状态);
}else{//parent
双速读;
关闭(pipeFD[1]);//关闭父级的写入端
而(1){
如果(读取(pipeFD[0],&speed\u read,sizeof(speed\u read))>0){
if(speed_readMAX_I){//最多读取输入的MAX_I行
printf(“我现在将退出标志发送给家长\n”);
写入(pipeFD[1],&exit_符号,sizeof(double));
自由线;
打破
}
if(写入(pipeFD[1],&speed,sizeof(double)>0)){
printf(“%d在%d处写入速度为%f\n”,getpid(),i,速度);
}else{printf(“在管道上写入失败\n”);}
睡眠(延迟);
}
自由线;
}
下面是打印的内容:


15032开始

15032在1写下速度为0.345670

进程15031从子进程收到0.000000

15032在2写下速度是12.678890

进程15031从子进程收到0.000000

15032在3处写道,速度为34.789870

进程15031从子进程收到0.000000

15032在4写下速度为0.000000

进程15031从子进程收到0.000000

15032在5处写道,速度为12.009288

进程15031从子进程收到0.000000

我现在就把退出标志发给家长

父母结束


同样,日志文件包含以下内容:

百万

百万

百万

百万

0.000000

在read\u输入行中:

一定是

if(write(pipeFD[1], &speed, sizeof(double))>0){
在您的情况下,您不会写入
sizeof(double)
字节,而只写入1个字节

注意:read_input执行两次
free(line);
对于未定义的行为,必须在
if(i>MAX_i){

更正、汇编和执行后:

pi@raspberrypi:/tmp $ gcc -g -Wall p.c
pi@raspberrypi:/tmp $ cat input.txt 
1.2
2.3
3.45
7.8
9.12
12.345
pi@raspberrypi:/tmp $ ./a.out
15121 starts 
15121 at 1 wrote that speed is 1.200000
process 15120 received 1.200000 from child 
15121 at 2 wrote that speed is 2.300000
process 15120 received 2.300000 from child 
15121 at 3 wrote that speed is 3.450000
process 15120 received 3.450000 from child 
15121 at 4 wrote that speed is 7.800000
process 15120 received 7.800000 from child 
15121 at 5 wrote that speed is 9.120000
process 15120 received 9.120000 from child 
I'll send the exit sign to parent now
parent ended 
pi@raspberrypi:/tmp $ cat file.log
1.200000 
2.300000 
3.450000 
7.800000 
9.120000 
pi@raspberrypi:/tmp $ 

当您检测到EOF并执行
printf(“无需读取的内容”)时;
也执行
中断;
完成
,而
似乎更好。注意,当您在read\u input中到达输入文件的结尾时,您也可以发送退出标志。如果您不这样做,则如果输入文件的行数小于MAX\u I,则父级永远不会停止在那里写入任何要读取的内容


管道是一条小溪,但在哪里

因此,在您的情况下,主要是尽可能快地读取,而read_输入函数处于休眠状态,而您读取和写入相同的少量字节,您没有任何风险。否则,一般来说,当您在流中读取时,您需要循环,直到获得预期的字节数,例如,通过调用一个函数来替换
read
例如:

int read_block(int f, char * p, size_t sz)
{
  ssize_t n;

  while ((n = read(f, p, sz)) > 0) {
    if ((sz -= (size_t) n) == 0)
      return 1;
    p += n;
  }

  return -1;
}
在read_中输入以下行:

一定是

if(write(pipeFD[1], &speed, sizeof(double))>0){
在您的情况下,您不会写入
sizeof(double)
字节,而只写入1个字节

注意:read_input执行两次
free(line);
对于未定义的行为,必须在
if(i>MAX_i){

更正、汇编和执行后:

pi@raspberrypi:/tmp $ gcc -g -Wall p.c
pi@raspberrypi:/tmp $ cat input.txt 
1.2
2.3
3.45
7.8
9.12
12.345
pi@raspberrypi:/tmp $ ./a.out
15121 starts 
15121 at 1 wrote that speed is 1.200000
process 15120 received 1.200000 from child 
15121 at 2 wrote that speed is 2.300000
process 15120 received 2.300000 from child 
15121 at 3 wrote that speed is 3.450000
process 15120 received 3.450000 from child 
15121 at 4 wrote that speed is 7.800000
process 15120 received 7.800000 from child 
15121 at 5 wrote that speed is 9.120000
process 15120 received 9.120000 from child 
I'll send the exit sign to parent now
parent ended 
pi@raspberrypi:/tmp $ cat file.log
1.200000 
2.300000 
3.450000 
7.800000 
9.120000 
pi@raspberrypi:/tmp $ 

当您检测到EOF并执行
printf(“无需读取的内容”)时;
也执行
中断;
完成
,而
似乎更好。注意,当您在read\u input中到达输入文件的结尾时,您也可以发送退出标志。如果您不这样做,则如果输入文件的行数小于MAX\u I,则父级永远不会停止在那里写入任何要读取的内容


管道是一条小溪,但在哪里

因此,在您的情况下,主要是尽可能快地读取,而read_输入函数处于休眠状态,而您读取和写入相同的少量字节,您没有任何风险。否则,一般来说,当您在流中读取时,您需要循环,直到获得预期的字节数,例如,通过调用一个函数来替换
read
例如:

int read_block(int f, char * p, size_t sz)
{
  ssize_t n;

  while ((n = read(f, p, sz)) > 0) {
    if ((sz -= (size_t) n) == 0)
      return 1;
    p += n;
  }

  return -1;
}

此外,代码应准备好进行部分读/写操作,该操作至少处理1个字节,但不处理完整的
sizeof(double)
@NateEldredge是的,管道是一条流。我没有这样做,因为我担心这对OP来说太复杂了,但最后你帮我改变主意,我会编辑我的answer@Bruno.这真的很有帮助。我的代码确实有很多错误。我将利用您的其他注释对其进行改进。写入的管道比管道小缓冲区大小是原子大小,并且
sizeof(double)
比管道缓冲区大小小得多。如果读取
sizeof(double)
字节并仅写入
sizeof(double)
字节在任何时候,都不会有部分读取和写入。@JonathanLeffler哦,是的,你是对的:此外,代码应该为部分读取/写入的可能性做好准备,该部分读取/写入至少处理1个字节,但不处理完整的
大小(双字节)
@NateEldredge是的,管道就是一条流。我没有这样做,因为我担心这对用户来说太复杂了