管道并不是每次在C中都给出相同的结果
我试图通过父进程读取文件,将内容发送到两个子进程,子进程将内容写入共享内存段。然而,每次运行时,我都会得到不同的输出,我不知道为什么 我使用两个命名管道,在写入共享内存后,父进程打开共享内存并读取每个内存的内容 第一个子对象在获取时写入内存,但第二个子对象将转换为十六进制 这是我的主要功能;假设管道并不是每次在C中都给出相同的结果,c,process,pipe,named-pipes,C,Process,Pipe,Named Pipes,我试图通过父进程读取文件,将内容发送到两个子进程,子进程将内容写入共享内存段。然而,每次运行时,我都会得到不同的输出,我不知道为什么 我使用两个命名管道,在写入共享内存后,父进程打开共享内存并读取每个内存的内容 第一个子对象在获取时写入内存,但第二个子对象将转换为十六进制 这是我的主要功能;假设stringtohex()工作正常 int main() { pid_t pid_1, pid_2; int fd, sd; // pipes const int SIZ
stringtohex()
工作正常
int main()
{
pid_t pid_1, pid_2;
int fd, sd; // pipes
const int SIZE = 4096;
const char infile[] = "in.txt";
FILE *tp; // file pointers
pid_1 = fork();
if (pid_1 < 0)
{
fprintf(stderr, "Fork 1 failed");
return(1);
}
if (pid_1 > 0)
{
pid_2 = fork();
if (pid_2 < 0)
{
fprintf(stderr, "Fork 2 failed");
return(1);
}
if (pid_2 > 0) // parent
{
tp = fopen(infile, "r");
if (tp == 0)
{
fprintf(stderr, "Failed to open %s for reading", infile);
return(1);
}
mknod(PIPE_NAME_1, S_IFIFO | 0666, 0);
mknod(PIPE_NAME_2, S_IFIFO | 0666, 0);
fd = open(PIPE_NAME_1, O_WRONLY);
sd = open(PIPE_NAME_2, O_WRONLY);
if (fd > 0 && sd > 0)
{
char line[300];
while (fgets(line, sizeof(line), tp))
{
int len = strlen(line);
int num_1 = write(fd, line, len);
int num_2 = write(sd, line, len);
if (num_1 != len || num_2 != len)
perror("write");
else
printf("Ch 1: wrote %d bytes\n", num_1);
printf("Ch 2: wrote %d bytes\n", num_2);
}
close(fd);
close(sd);
}
fclose(tp);
wait(NULL);
int shm_fd = shm_open("Ch_1", O_RDONLY, 0666);
if (shm_fd == -1)
{
fprintf(stderr, "Failed: Shared Memory 1");
exit(-1);
}
int shm_sd = shm_open("Ch_2", O_RDONLY, 0666);
if (shm_sd == -1)
{
fprintf(stderr, "Failed: Shared Memory 2");
exit(-1);
}
void *ptr = mmap(0, SIZE, PROT_READ, MAP_SHARED, shm_fd, 0);
if (ptr == MAP_FAILED)
{
printf("Map failed 1\n");
return -1;
}
void *ptr2 = mmap(0, SIZE, PROT_READ, MAP_SHARED, shm_sd, 0);
if (ptr2 == MAP_FAILED)
{
printf("Map failed 2\n");
return -1;
}
fprintf(stdout, "Normal input: \n%s\n", ptr);
fprintf(stderr, "Hexadecimal: \n%s\n", ptr2);
}
else // second child
{
// open shared memory segment
int shm_child_2 = shm_open("Ch_2", O_CREAT | O_RDWR, 0666);
// configure the size of the shared memory segment
ftruncate(shm_child_2, SIZE);
// map the pointer to the segment
void *ptr_child_2 = mmap(0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_child_2, 0);
if (ptr_child_2 == MAP_FAILED)
{
printf("Map failed 3\n");
return -1;
}
// configure named pipe
mknod(PIPE_NAME_2, S_IFIFO | 0666, 0);
sd = open(PIPE_NAME_2, O_RDONLY);
if (sd > 0) // reading from pipe
{
int num;
char s[300];
while ((num = read(sd, s, sizeof(s))) > 0)
{
// convert to hexadecimal
char hex[strlen(s) * 2 + 1];
stringtohex(s, hex);
// write into segment
sprintf(ptr_child_2, "%s", hex);
ptr_child_2 += strlen(s) * 2;
}
close(sd);
}
exit(0);
}
}
else // first child
{
// create shared memory segment
int shm_child_1 = shm_open("Ch_1", O_CREAT | O_RDWR, 0666);
// configure the size of the shared memory segment
ftruncate(shm_child_1, SIZE);
// map the pointer to the segment
void *ptr_child_1 = mmap(0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_child_1, 0);
if (ptr_child_1 == MAP_FAILED)
{
printf("Map failed 4\n");
return -1;
}
// configure named pipe
mknod(PIPE_NAME_1, S_IFIFO | 0666, 0);
fd = open(PIPE_NAME_1, O_RDONLY);
if (fd > 0) // reading from pipe
{
int num;
char s[300];
while ((num = read(fd, s, strlen(s))) > 0)
{
// write into segment
sprintf(ptr_child_1, "%s", s);
ptr_child_1 += strlen(s);
}
close(fd);
}
exit(0);
}
return 0;
}
结果如下:
正常输入:
哈伦
萨斯马兹
59900
1234
Aaaa4
十六进制:
484152554E0A7361736D617A0A35393930300A313233340A416161
或
正常输入:
哈伦
萨斯马兹
asmaz59900
1234
Aaaa
十六进制:
484152554E0A7361736D617A0A35393930300A0A313233340A416161FF03我发现你的代码真的不可读。我建议不要创建这么长的函数——在小的可读部分之间拆分函数
read
返回ssize\u t
,而不是int
strlen
返回size\u t
,而不是int
。请使用一致的缩进strlen
-s
是否真的以零结尾?例如,在read(fd,s,strlen(s))
-s
未初始化。您不能假设从read(fd,s,sizeof(s))
读取的内容将以零结尾。您应该使用read
返回值来确定数据的长度。我已经习惯了C语言编程,我知道代码的结构很混乱,但我正在努力专注于这项任务。谢谢你的建议。我不认为我在while((num=read(sd,s,sizeof(s))>0){//convert to hexadecimal char hex[strlen(s)*2+1];
-为什么strlen(s)
工作?你不会在管道中写入零字节。你的代码:while((num=read(sd,s,sizeof))>0){char hex[strlen(s)*2+1];
应在数组定义中使用num*2+1
。应告知您的stringtohex()
要转换多少字节。可能存在错误,因为stringtohex()
不是一个字符串,而是一个没有空字节标记结尾的字节数组。你知道当你“假设”某个东西起作用时会发生什么吗?它让你和我都很难堪。你没有显示代码来转储读取的内容,或者由stringtohex()生成的内容,例如,因此你不知道发生了什么。为什么要使用mknod()
要创建FIFO而不是mkfifo()
?
Harun
sasmaz
59900
1234
Aaaa