我需要创建具有3个进程的程序:
/dev/urandom
,并通过管道每个周期向第二个进程发送15个字符。这是我到目前为止写的。使用管道的通信可以正常工作,但是fifo存在一些问题-当我将n
更改为较大的数字(例如100000或1000000)时,程序无法启动。当它较小时(例如500或1000),该程序将起作用。这可能是什么原因?
这是我的运行方式:
cat /dev/urandom | ./a.out
这是代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#define FIFO "my_fifo"
int main(void) {
int pdesk[2];
char buf[15];
char buffer[15];
char hex[30];
char f[30];
int len;
int n;
n = 100;
umask(0);
mkfifo(FIFO, 0666);
pipe(pdesk);
if (fork() == 0) {
for (int i = 0; i < n; i++) {
read(STDIN_FILENO, buffer, 15);
write(pdesk[1], buffer, 15);
}
close(pdesk[1]);
} else {
sleep(1);
int fp;
for(int i = 0; i < n; i++) {
read(pdesk[0], buf, 15);
for(int a = 0, b = 0; b < 30; ++a, b+= 2)
sprintf(hex + b, "%02x", buf[a] & 0xff);
fp = open(FIFO, O_WRONLY);
write(fp, hex, 30);
close(fp);
usleep(10000);
}
close(pdesk[0]);
}
if (fork() == 0) {
sleep(2);
int fp;
for (int i = 0; i < n; i++) {
fp = open(FIFO, O_RDONLY);
read(fp, f, 30);
printf("Odczytano: %s\n", f);
close(fp);
usleep(10000);
}
}
}
答案 0 :(得分:1)
如果我理解您的代码正确,它将执行以下操作:
使用第一个fork
,您将启动一个从stdin读取并写入管道的子项。
您的父进程从管道读取并写入FIFO。
父进程完成循环后,它将调用第二个fork
以创建另一个子进程,该子进程将从FIFO中读取并打印数据。
当循环计数太大时,您将达到FIFO的缓冲区限制,而父级将阻塞,因为没有进程从FIFO中读取。当该进程无法写入FIFO时,它将永远不会创建预期从FIFO读取的子进程。
我认为主要的问题是,您应该在开始从管道读取数据并将其写入FIFO的循环之前创建第二个子代。
一些补充说明:
使用cat /dev/urandom | ./a.out
时,程序不会直接读取/dev/urandom
。它从行为可能不同的管道读取数据。
您应始终检查read
的返回值。它会告诉您已读取的字节数可能少于您要求的字节数。如果要精确地包含15个字符,则少于15个字符可能需要阅读几次。
write
也是如此。
答案 1 :(得分:0)
非常感谢。当显示数据的进程位于其他子进程之上时,它最终将工作。
使用cat / dev / urandom | ./a.out您的程序不会直接读取/ dev / urandom。它从行为可能不同的管道读取。
我该如何更改?
程序还需要以与/ dev / urandom相同的方式读取文件,例如:
cat file.txt | ./a.out
我听取了您的建议,开始检查read的值,现在它没有超出文件范围。问题是我不知道如何检查调用了哪个参数(因此我无法检查文件的长度)-如果是file.txt,/ dev / urandom,没有其他任何东西。我尝试过
int main(char argc, char* argv[])
但是argv始终是./a.out,无论我叫什么。有什么办法可以检查吗?