在 fork 后使用读/写管道 2 字符串
Posted
技术标签:
【中文标题】在 fork 后使用读/写管道 2 字符串【英文标题】:Pipe 2 string using read/write after fork 【发布时间】:2022-01-03 03:51:35 【问题描述】:我很难理解在线课程中管道和叉子如何协同工作。首先,我想在 printf 和 when all read/write end cat 两个字符串合为一个的下方键入两个字符串。 我被困在两个孩子的读/写中,问题是它与我想要的不匹配,因为首先打印字符串然后打开通道输入。也许这是一件小事,但我开始将 C 用于在线课程。读写功能是强制性的。
String 1:
sdfsdfsdf
String 2:
Sdfsdfdsfsdfsd
String cat:
sdfsdfsdfSdfsdfdsfsdfsd
这是我目前的代码。
int main()
int fd1[2],fd2[2];
int status, pid;
pipe(fd1);
printf("String 1: \n");
pid = fork();
if(pid == 0) /* child 1*/
close(fd1[0]);
char cad1[100];
read(0,&cad1,100);
write(fd1[1],&cad1, 100);
close(fd1[1]);
exit(0);
else /* father*/
close(fd1[1]);
printf("String 2: \n");
pipe(fd2);
pid = fork();
if(pid == 0) /* child 2 */
close(fd2[0]);
close(fd1[0]);
char cad2[100];
read(0,&cad2,100);
write(fd2[1],&cad2, 100);
close(fd2[1]);
exit(0);
close(fd2[0]);
/* wait every child */
wait(&status);
wait(&status);
return 0;
我的输出是这样的:
String 1:
String 2:
cvbcvbcvbcvb
cvbcvbcvbcvb
to cat 我的代码(未在我认为在 cat 之前调用两个管道到 char [] 变量的代码中实现。
任何改进我的代码的建议。 提前致谢。
【问题讨论】:
父代码需要从两个管道中读取来收集子节点的数据,然后将它们连接起来。您需要注意读取了多少字节,以免写入的字节数超过读取的字节数。第二个孩子应该关闭fd1[0]
和fd1[1]
,因为它不会使用它们。您需要担心换行符和空字节——read()
返回的信息不是字符串,而是包含换行符。
【参考方案1】:
这是我的代码,大致基于您的代码。正如我在comment 中所说,父代码需要从两个管道中读取以从子管道中收集数据,然后将它们连接起来。您需要注意读取了多少字节,以免写入的字节数超过读取的字节数。第二个孩子应该关闭fd1[0]
和fd1[1]
,因为它不会使用它们。您需要担心换行符和空字节——read()
返回的信息不是字符串,而是包含换行符。
我选择使用fgets()
从标准输入中读取,因为它确实返回了一个字符串并删除了换行符。我也将一些信息写入标准输出。连接的字符串是使用snprintf()
创建的。
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
static inline void syserr_exit(const char *fmt, ...)
va_list args;
int errnum = errno;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
if (errnum != 0)
fprintf(stderr, "%d: %s\n", errnum, strerror(errnum));
exit(EXIT_FAILURE);
int main(void)
int fd1[2], fd2[2];
int pid1, pid2;
if (pipe(fd1) < 0 || pipe(fd2) < 0)
syserr_exit("Failed to create two pipes: ");
else if ((pid1 = fork()) < 0)
syserr_exit("Failed to fork() child 1: ");
else if (pid1 == 0)
/* Child 1*/
close(fd1[0]);
close(fd2[0]);
close(fd2[1]);
char cad1[100];
printf("String 1: \n");
fflush(stdout);
if (fgets(cad1, sizeof(cad1), stdin) == NULL)
syserr_exit("child 1 - failed to read from standard input: ");
cad1[strcspn(cad1, "\r\n")] = '\0';
write(fd1[1], cad1, strlen(cad1));
/* Should error check the write! */
printf("child 1 wrote [%s] to the parent process\n", cad1);
close(fd1[1]);
exit(0);
else if ((pid2 = fork()) < 0)
syserr_exit("Failed to fork child 2: ");
else if (pid2 == 0)
/* Child 1*/
close(fd1[0]);
close(fd1[1]);
close(fd2[0]);
printf("String 2: \n");
fflush(stdout);
char cad2[100];
if (fgets(cad2, sizeof(cad2), stdin) == NULL)
syserr_exit("child 2 - failed to read from standard input: ");
cad2[strcspn(cad2, "\r\n")] = '\0';
write(fd2[1], cad2, strlen(cad2));
/* Should error check the write! */
printf("child 2 wrote [%s] to the parent process\n", cad2);
close(fd2[1]);
exit(0);
else
/* Parent */
char buffer1[100];
char buffer2[100];
close(fd2[1]);
close(fd1[1]);
ssize_t sz1 = read(fd1[0], buffer1, sizeof(buffer1));
buffer1[sz1] = '\0';
close(fd1[0]);
ssize_t sz2 = read(fd2[0], buffer2, sizeof(buffer2));
buffer2[sz2] = '\0';
close(fd2[0]);
size_t tlen = sz1 + sz2 + sizeof("[]+[]");
char concat[tlen];
snprintf(concat, sizeof(concat), "[%s]+[%s]", buffer1, buffer2);
/* wait for both children */
int s1, s2;
int c1 = wait(&s1);
int c2 = wait(&s2);
printf("The one child (%d) exited with status 0x%.4X\n", c1, s1);
printf("T'other child (%d) exited with status 0x%.4X\n", c2, s2);
printf("Received from %d (%zu bytes) [[%s]]\n", pid1, sz1, buffer1);
printf("Received from %d (%zu bytes) [[%s]]\n", pid2, sz2, buffer2);
printf("Concatenated data: <<%s>>\n", concat);
return 0;
产生了一个样本运行:
$ ./pipe43
String 1:
String 2:
Vultures keep the world clean.
child 2 wrote [Vultures keep the world clean.] to the parent process
Hypersonic transport planes are as ubiquitous as pink elephants
child 1 wrote [Hypersonic transport planes are as ubiquitous as pink elephants] to the parent process
The one child (69005) exited with status 0x0000
T'other child (69004) exited with status 0x0000
Received from 69004 (63 bytes) [[Hypersonic transport planes are as ubiquitous as pink elephants]]
Received from 69005 (30 bytes) [[Vultures keep the world clean.]]
Concatenated data: <<[Hypersonic transport planes are as ubiquitous as pink elephants]+[Vultures keep the world clean.]>>
$
【讨论】:
以上是关于在 fork 后使用读/写管道 2 字符串的主要内容,如果未能解决你的问题,请参考以下文章