【七】 进程间通信——(FIFO)有名管道
我们向管道中写入数据时,linux将不保证写入的原子性,管道缓冲区一有空闲区域,写进程就会试图相关到中写入数据。如果杜金城不读走管道缓冲区的数据,那么写操作将会一直阻塞。
只有读端存下的时候,向管道中写数据才有意义。否则相关到中写入数据的进程将受到内核传来的SIFPIPE,我们可以通过这个信号来判断读端是否退出。
有名管道和无名管道(PIPE)最大的不同在于,有名管道可以在互不相关的两个进程间通信,有名管道在文件中是可见的,但是它只是挂一个名字而已,重头到尾,该文件的大小都是0。它同样是不支持ISEEK()函数操作。并且是遵循先进先出的规则。
写一个fifo的程序应该包含的头文件有:#include <unistd.h>、#include <fcntl.h>、#include <sys/types.h>
int mkfifo(const char *filename,mode_t mode);创建一个管道,并指定这个管道文件的读写属性
int main()
{
if(mkfifo("fifo.demo", 0666) == -1)
{
perror("mkfifo");
exit(-1);
}
return 0;
}
/*readfifo.c*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#define N 64
int main()
{
int fd;
char buf[N];
ssize_t n;
//if ((fd = open("myfifo", O_RDONLY)) == -1)
if ((fd = open("myfifo", O_RDONLY | O_NONBLOCK)) == -1)
{
perror("open for reading");
exit(-1);
}
printf("read:open\n");
while (1)
{
sleep(10);
n = read(fd, buf, N);//abc
buf[n] = 0;
printf("n=%d*%s\n", n, buf);
}
exit(0);
}
/*Writefifo.c*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#define N 64
int main()
{
int fd;
char buf[N];
//if ((fd = open("myfifo", O_WRONLY)) == -1)
//if ((fd = open("myfifo", O_WRONLY | O_NONBLOCK)) == -1)
if ((fd = open("myfifo", O_RDWR)) == -1)
{
// perror("open for writing");
fprintf(stderr, "errno=%d %s\n", errno, strerror(errno));
exit(-1);
}
printf("write:open\n");
while (fgets(buf, N, stdin) != NULL)//abc\n\0
{
buf[strlen(buf)-1] = 0;//abc\0
write(fd, buf, strlen(buf));//abc
// write(fd, buf, strlen(buf)+1);//abc\0
}
exit(0);
}
接下来我们要完成一个“利用fifo和信号机制的进程间同步通信”的程序: