C 管道写入/读取双精度序列失败
C pipe to write / read sequence of doubles fails
对于这个 C 项目,我正在尝试使用管道让 parent 进程与 child 进行通信。 child 应该从 txt 文件(包含实数)中读取行(每秒一行)并使用管道提供 parent,而 parent 又应该从管道读取并写入数字到日志文件中。但是 parent 进程只读取 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);
}
这是打印的内容:
15032 次启动
15032 at 1 wrote that speed is 0.345670
进程 15031 从 child
收到 0.000000
15032 at 2 wrote that speed is 12.678890
进程 15031 从 child
收到 0.000000
15032 at 3 wrote that speed is 34.789870
进程 15031 从 child
收到 0.000000
15032 at 4 wrote that speed is 0.000000
进程 15031 从 child
收到 0.000000
15032 at 5 wrote that speed is 12.009288
进程 15031 从 child
收到 0.000000
我现在将出口标志发送到 parent
parent结束
同样,日志文件包含以下内容:
0.000000
0.000000
0.000000
0.000000
0.000000
在read_input行:
if(write(pipeFD[1], &speed, sizeof(double)>0)){
必须
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("Nothing there to read \n");
并执行 break;
来完成时 while
似乎更好。请注意,当您到达 read_input 中的输入文件末尾时,您也可以发送 exit_sign。如果你不这样做,如果输入文件少于 MAX_I 行
A pipe 是 stream 但 reading or writing pipe data is atomic if the size of data written is not greater than PIPE_BUF where PIPE_BUF is at least 512 bytes, and 4096 under Linux
所以在你的情况下,在 main 你尽可能快地阅读并且 read_input 函数休眠,而你读取和写入相同的少量字节,您没有风险。否则,通常当您在流中读取时,您需要循环直到获得预期的字节数,例如通过调用像 :
这样的函数来替换 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;
}
对于这个 C 项目,我正在尝试使用管道让 parent 进程与 child 进行通信。 child 应该从 txt 文件(包含实数)中读取行(每秒一行)并使用管道提供 parent,而 parent 又应该从管道读取并写入数字到日志文件中。但是 parent 进程只读取 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);
}
这是打印的内容:
15032 次启动
15032 at 1 wrote that speed is 0.345670
进程 15031 从 child
收到 0.00000015032 at 2 wrote that speed is 12.678890
进程 15031 从 child
收到 0.00000015032 at 3 wrote that speed is 34.789870
进程 15031 从 child
收到 0.00000015032 at 4 wrote that speed is 0.000000
进程 15031 从 child
收到 0.00000015032 at 5 wrote that speed is 12.009288
进程 15031 从 child
收到 0.000000我现在将出口标志发送到 parent
parent结束
同样,日志文件包含以下内容:
0.000000
0.000000
0.000000
0.000000
0.000000
在read_input行:
if(write(pipeFD[1], &speed, sizeof(double)>0)){
必须
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("Nothing there to read \n");
并执行 break;
来完成时 while
似乎更好。请注意,当您到达 read_input 中的输入文件末尾时,您也可以发送 exit_sign。如果你不这样做,如果输入文件少于 MAX_I 行
A pipe 是 stream 但 reading or writing pipe data is atomic if the size of data written is not greater than PIPE_BUF where PIPE_BUF is at least 512 bytes, and 4096 under Linux
所以在你的情况下,在 main 你尽可能快地阅读并且 read_input 函数休眠,而你读取和写入相同的少量字节,您没有风险。否则,通常当您在流中读取时,您需要循环直到获得预期的字节数,例如通过调用像 :
这样的函数来替换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;
}