使用FIFO来进行两个进程间的通信
2017-04-02 13:41
501 查看
使用命名管道的操作和使用普通的文本文件类似,都是系统调用open函数去打开创建好的管道,使用read,write函数操作,操作完成后用close函数关闭。
从FIFO中读取数据的规则是:
1,如果一个进程为了从fifo中读取数据而阻塞打开fifo,n那么称该进程内的读操作为设置了阻塞标志的读操作。
2,如果有进程写打开了fifo,而且当前fifo内没有数据,则对于这于设置了阻塞标志的读操作来说,将一直阻塞,对于没有设置阻塞标志读操作来说则返回-1,当前errno值为EGIN,提醒以后再试。
3,对于设置阻塞标志的读操作来说,造成阻塞的原因有两种:① 当前fifo内有数据,但有其他的进程在读这些数据。②fifo里面没有数据。解阻塞的原因则是fifo有新的数据写入不管新写入数据量的大小,也不论读操作请求多少数据。
4,读打开的阻塞标志只对本进程第一个读操作施加作用,如果本进程内有多个读操作序列,则在第一个读操作被唤醒并完成读操作后,其他要执行的读操作将不再阻塞。即使在执行读操作时,fifo里面没有数据也一样(读操作返回0)。
5,如果没有写进程打开fifo,则设置了阻塞标志的读操作也会阻塞。
向fifo中写入数据的规则是:
1.如果一个进程为了向fifo中写数据而阻塞打开fifo,那么称该进程内的写操作为设置了阻塞标志的写操作。
2.对于设置了阻塞标志的写操作,当要写入的数据量不大于PIPE_BUF时,Linux将保证写入的原子性,如果此时管道空闲缓冲区不足以容纳要写入的数据时,则进入睡眠,知道当缓冲区能够容下要写入数据字节数时,才开始进行一次性写操作。
3.当要写入的数据量大于PIPE_BUF时,linux不能保证写入的原子性,在写满fifo空闲缓冲区后,写操作返回。
4.要写入的数据量不大于PIPE_BUF时,linux将保证写入原子性,如果当前缓冲区能容下要写的数据,则写完后返回,相反的话,返回EAGIN错误,提醒以后再写。
write_fifo.c:
#include<sys/types.h>
#include<sys/stat.h>
#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
#include<limits.h>
#include<stdlib.h>
#include<time.h>
#define BUFES PIPE_BUF
int main(void)
{
int fd;
int n,i;
char buf[BUFES];
time_t tp;
printf("%d\n",getpid());
if((fd=open("fifo1",O_WRONLY))<0)
{
printf("open failed\n");
exit(1);
}
for(i=0;i<10;i++)
{
time(&tp);
n=sprintf(buf,"write fifo %d sends %s",getpid(),ctime(&tp));
printf("send msg:%s\n",buf);
if((write(fd,buf,n+1))<0)
{
printf("write failed!\n");
close(fd);
exit(1);
}
sleep(3);
}
close(fd);
exit(0);
}
Step 1: lishun@lishun-Qt:~$ mkfifo -m 0666 fifo1 (建立管道)
Step2: gcc write_fifo.c -o write
Ste2: ./write (write 当前 阻塞,一直到运行read)
Step3: gcc read_fifo.c -o read
Step4: ./read
从FIFO中读取数据的规则是:
1,如果一个进程为了从fifo中读取数据而阻塞打开fifo,n那么称该进程内的读操作为设置了阻塞标志的读操作。
2,如果有进程写打开了fifo,而且当前fifo内没有数据,则对于这于设置了阻塞标志的读操作来说,将一直阻塞,对于没有设置阻塞标志读操作来说则返回-1,当前errno值为EGIN,提醒以后再试。
3,对于设置阻塞标志的读操作来说,造成阻塞的原因有两种:① 当前fifo内有数据,但有其他的进程在读这些数据。②fifo里面没有数据。解阻塞的原因则是fifo有新的数据写入不管新写入数据量的大小,也不论读操作请求多少数据。
4,读打开的阻塞标志只对本进程第一个读操作施加作用,如果本进程内有多个读操作序列,则在第一个读操作被唤醒并完成读操作后,其他要执行的读操作将不再阻塞。即使在执行读操作时,fifo里面没有数据也一样(读操作返回0)。
5,如果没有写进程打开fifo,则设置了阻塞标志的读操作也会阻塞。
向fifo中写入数据的规则是:
1.如果一个进程为了向fifo中写数据而阻塞打开fifo,那么称该进程内的写操作为设置了阻塞标志的写操作。
2.对于设置了阻塞标志的写操作,当要写入的数据量不大于PIPE_BUF时,Linux将保证写入的原子性,如果此时管道空闲缓冲区不足以容纳要写入的数据时,则进入睡眠,知道当缓冲区能够容下要写入数据字节数时,才开始进行一次性写操作。
3.当要写入的数据量大于PIPE_BUF时,linux不能保证写入的原子性,在写满fifo空闲缓冲区后,写操作返回。
4.要写入的数据量不大于PIPE_BUF时,linux将保证写入原子性,如果当前缓冲区能容下要写的数据,则写完后返回,相反的话,返回EAGIN错误,提醒以后再写。
write_fifo.c:
#include<sys/types.h>
#include<sys/stat.h>
#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
#include<limits.h>
#include<stdlib.h>
#include<time.h>
#define BUFES PIPE_BUF
int main(void)
{
int fd;
int n,i;
char buf[BUFES];
time_t tp;
printf("%d\n",getpid());
if((fd=open("fifo1",O_WRONLY))<0)
{
printf("open failed\n");
exit(1);
}
for(i=0;i<10;i++)
{
time(&tp);
n=sprintf(buf,"write fifo %d sends %s",getpid(),ctime(&tp));
printf("send msg:%s\n",buf);
if((write(fd,buf,n+1))<0)
{
printf("write failed!\n");
close(fd);
exit(1);
}
sleep(3);
}
close(fd);
exit(0);
}
read_fifo.c #include<sys/types.h> #include<sys/stat.h> #include<unistd.h> #include<stdlib.h> #include<stdio.h> #include<limits.h> #include<fcntl.h> #define BUFES PIPE_BUF int main(void) { int fd; int len; char buf[BUFES]; mode_t mode =0666; if((fd=open("fifo1",O_RDONLY))<0) { printf("Open failed"); exit(1); } while((len=read(fd,buf,BUFES))>0) { printf("Read_fifo read:%s\n",buf); } close(fd); exit(0); return 0; }
Step 1: lishun@lishun-Qt:~$ mkfifo -m 0666 fifo1 (建立管道)
Step2: gcc write_fifo.c -o write
Ste2: ./write (write 当前 阻塞,一直到运行read)
Step3: gcc read_fifo.c -o read
Step4: ./read
相关文章推荐
- [ZZ]使用命名管道通过网络在进程之间进行通信
- C#使用命名管道通过网络在进程之间进行通信
- 使用AIDL来进行跨进程通信
- 安卓Service组件使用系列6:使用AIDL完成两个进程间的通信
- Linux下的有名管道(05)---使用两个管道实现两个进程之间的通信(对讲机模式)
- 如何:使用匿名管道在本地进程之间进行通信(C#)
- Linux下的有名管道(06)---使用两个管道实现两个进程之间的通信(手机模式)
- 关于使用UDP套接字进行本地进程通信
- C#中使用SendMessage进行进程通信,可以发送字符串。
- linux进程间的通信(C): 使用信号量进行同步的共享内存机制
- 使用Windows API实现两个进程间(含窗体)的通信
- 线程间无需特别的手段进行通信,因为线程间可以共享数据结构,也就是一个全局变量可以被两个线程同时使用,不过要注意的是线程间需要做好同步。
- 两个进程进行通信的简单例子
- 使用Intent和Bundle在两个Activity之间进行通信添加上一步按钮实现回退
- 使用CreateNamedPipe进行 进程通信的示例
- boost线程库学习--(4)两个线程间使用队列进行通信
- C#中使用命名管道进行进程通信的实例
- C#中使用命名管道进行进程通信的实例
- 控制台程序使用SendMessage进行进程间的通信
- 使用tcp socket进行跨进程/网络通信