C read()在linux中等待吗?
我正在学习Linux中的pipe()系统调用。以下是我有疑问的代码片段:C read()在linux中等待吗?,c,linux,C,Linux,我正在学习Linux中的pipe()系统调用。以下是我有疑问的代码片段: #define MSGSIZE 16 char* msg1 = "hello, world #1"; char* msg2 = "hello, world #2"; char* msg3 = "hello, world #3"; int main() { char inbuf[MSGSIZE]; int p[2], i; if (pip
#define MSGSIZE 16
char* msg1 = "hello, world #1";
char* msg2 = "hello, world #2";
char* msg3 = "hello, world #3";
int main()
{
char inbuf[MSGSIZE];
int p[2], i;
if (pipe(p) < 0)
exit(1);
int pid=fork();
if(pid==0){
sleep(2); ///Making parent process sleep so that child process moves ahead
write(p[1], msg1, MSGSIZE);
write(p[1], msg2, MSGSIZE);
write(p[1], msg3, MSGSIZE);
printf("Done writing");
}
else{
printf("child process\n");
for (i = 0; i < 3; i++) {
read(p[0], inbuf, MSGSIZE);
printf("%s\n", inbuf);
}
}
return 0;
}
正如我们所看到的,子进程在完成写入调用之前已经启动。在这里,read call似乎在等待什么。我在手册页中找不到有关此行为的文档。
有人能简单地解释一下这里发生了什么吗?关键词:同步 终端的输出由两个进程共享。终端是如何在内部处理同步的,谁知道呢,但是您可以同步进程的输出(例如,通过共享内存和互斥或信号量)。因此,不要依赖于输出的顺序,即先调用什么,谁在等待谁 或者简单地为每次调用
printf
使用一个时间戳
我在这里回答了一个类似的问题:。默认情况下,read()会一直阻塞,直到有可用的输入或输入结束
POSIX(IEEE Std 1003-1)标准规定,管道至少可以容纳512字节的数据。(这意味着write()将立即成功,即使数据仍在管道中,另一端尚未读取。)
主进程将数据写入管道并立即退出。由于子进程的读取端仍处于打开状态,因此它可以稍后读取主进程写入的数据。我冒昧地对您的代码进行了一些润色,特别是: 父进程和子进程 我修改了
IF
语句以正确标识父进程和子进程。从fork()手册页,关于它的返回值:
成功时,子进程的PID将在
父级,并且在子级中返回0。失败时,-1为
在父进程中返回,未创建子进程,错误号为
适当地设置
在这种情况下,这没什么大不了的,但肯定会导致一些问题
关闭管道
我在未使用和完成读/写时都关闭了管道末端。看看为什么它在这里很重要:
退出和等待
我让家长等待孩子的终止,以免留下一个孤立的过程(在更复杂和极端的情况下)导致系统资源匮乏
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#define MSGSIZE 16
char* msg1 = "hello, world #1";
char* msg2 = "hello, world #2";
char* msg3 = "hello, world #3";
int main()
{
char inbuf[MSGSIZE];
int p[2], i;
if (pipe(p) < 0)
exit(1);
int pid = fork();
if (pid > 0) {
// Parent process
close(p[0]); // Closing unused pipe
//sleep(2);
write(p[1], msg1, MSGSIZE);
write(p[1], msg2, MSGSIZE);
write(p[1], msg3, MSGSIZE);
close(p[1]); // Closing pipe after all writes are done
printf("Parent done writing\n");
wait(NULL);
} else if (pid == 0) {
// Child process
close(p[1]); // Closing unused pipe
printf("Child process\n");
for (i = 0; i < 3; i++) {
read(p[0], inbuf, MSGSIZE);
printf("%s\n", inbuf);
}
close(p[0]);
exit(0); // Child has terminated succesfully, exit.
} else {
fprintf(stderr, "Fork error.\n");
return 1;
}
return 0;
}
#包括
#包括
#包括
#包括
#定义MSGSIZE 16
char*msg1=“你好,世界1”;
char*msg2=“你好,世界2”;
char*msg3=“你好,世界3”;
int main()
{
char inbuf[MSGSIZE];
int p[2],i;
如果(管道(p)<0)
出口(1);
int-pid=fork();
如果(pid>0){
//父进程
关闭(p[0]);//关闭未使用的管道
//睡眠(2);
写入(p[1],msg1,MSGSIZE);
写入(p[1],msg2,MSGSIZE);
写入(p[1],msg3,MSGSIZE);
close(p[1]);//完成所有写入操作后关闭管道
printf(“父级完成写入\n”);
等待(空);
}否则如果(pid==0){
//子进程
关闭(p[1]);//关闭未使用的管道
printf(“子进程”);
对于(i=0;i<3;i++){
读取(p[0],inbuf,MSGSIZE);
printf(“%s\n”,inbuf);
}
接近(p[0]);
退出(0);//子项已成功终止,退出。
}否则{
fprintf(stderr,“Fork error.\n”);
返回1;
}
返回0;
}
简单的答案是,读取
会等待一些输入可用
更准确地说,文件可以在阻塞或非阻塞模式下打开。阻塞模式是默认模式。您可以通过将flags
参数中的O_NONBLOCK
传递到open
(例如open(filename,O_RDONLY | O_NONBLOCK)
)或在打开文件后调用fcntl(fd,F_SETFL,O_NONBLOCK)
,来选择非阻塞模式
在阻塞模式下,读取
通常会等待,直到读取至少一个字节。请注意,它不会等到读取了请求的字节数,即使有那么多字节可用。一次读取
调用返回多少字节取决于进程调度器的突发奇想。“正常”意味着您可以像
do n = read(…);
while (n > 0 || (n < 0 && errno == EINTR));
do n=read(…);
而(n>0 | |(n<0&&errno==EINTR));
并且要确信这不会是一个紧密的循环。注意,errno==EINTR
,这表示在读取任何内容之前,read
被中断。(返回0并不表示这一点,因为返回0表示文件结束,因此返回0更符合逻辑。)
如果文件处于非阻塞模式,则未读取任何内容的另一种情况是errno==EAGAIN
。在非阻塞模式下,如果没有可用数据,read
会立即返回,因此类似于上述循环的循环将是错误的
所有这一切也适用于
写入
,除了0表示文件结束。是的,它在返回之前等待输入。除非描述符是非阻塞的,read()
将阻塞,直到有可用的输入(或错误)。在文档中搜索O_NONBLOCK
标志。或中断(检查errno
以查看EINTR
)。顺便说一句:您应该检查函数read
和write
的返回值。不能保证它总是写入或读取完整的消息。可能需要多次重复调用以读取或写入其余部分。
do n = read(…);
while (n > 0 || (n < 0 && errno == EINTR));