这些通信方式各有各的特点,无名管道是最简单的常用于一对一的亲缘进程间通信的方
式,有名管道存在于文件系统之中,提供写入原子性特征,信号是唯一一种异步通信方式, 共享内存的效率最高,但是要结合信号量等同步互斥机制一起使用,消息队列提供一种带简 单消息标识的通信方式,套接字是一种更为宽泛意义上的进程间通信方式——它允许进程间 跨网络。
常说的管道通常指无名管道 (PIPE) 或者有名管道 (FIFO) ,但实际上套接字也都是 管道。这里先把 PIPE 和 FIFO 的相关接口摆出:
先来罗列 PIPE 的特征:
1,没有名字,因此无法使用 open( )。
2,只能用于亲缘进程间 (比如父子进程、兄弟进程、祖孙进程……) 通信。
3,半双工工作方式:读写端分开。
4,写入操作不具有原子性,因此只能用于一对一的简单通信情形。
5,不能使用 lseek( )来定位。
#include
#include
#include
#include
#include
//无名管道的使用
int main()
{
//创建一个数组,来装管道的读写端
int fd[2];
//创建无名管道
int ret = pipe(fd);
if(ret==-1){
perror("pipe()");
return -1;
}
//定义读写缓冲区
char wbuf[128];
char rbuf[128];
//创建一个子进程
pid_t pid = fork();
if(pid==0){//子进程
//从管道读数据
read(fd[0],rbuf,sizeof(rbuf)-1);
printf("你爹说:%s\n",rbuf);
}
if(pid>0){//父进程
//往管道写数据
fgets(wbuf,sizeof(wbuf),stdin);//从键盘获取输入的字符串
write(fd[1],wbuf,strlen(wbuf));
}
return 0;
}
有名管道 FIFO 的特征:
1,有名字,存储于普通文件系统之中。
2,任何具有相应权限的进程都可以使用 open( )来获取 FIFO 的文件描述符。
3,跟普通文件一样:使用统一的 read( )/write( )来读写。
4,跟普通文件不同:不能使用 lseek( )来定位,原因同 PIPE。
5,具有写入原子性,支持多写者同时进行写操作而数据不会互相践踏。
6,First In First Out,最先被写入 FIFO 的数据,最先被读出来。
rose.c
#include
#include
#include
#include
#include
#include
#include
//有名管道进程间通信
int main()
{
//access检测文件是否存在,F_OK,R_OK,W_OK,X_OK
if(access("/home/lsf/jincheng_course/myfifo",F_OK)==-1){//mufifo不存在则创建管道
//创建一个有名管道
int ret_fifo = mkfifo("/home/lsf/jincheng_course/myfifo",0777);
if(ret_fifo==-1){
perror("file exist");
}
}
//打开文件
int fd = open("/home/lsf/jincheng_course/myfifo",O_RDONLY);
if(fd==-1){
perror("open myfifo failed");
return -1;
}
char buf[128];
//读文件
while(1){
memset(buf,0,sizeof(buf));//清空
read(fd,buf,sizeof(buf)-1);
printf("[from jack]:%s\n",buf);
if(strcmp(buf,"bye\n")==0){
break;
}
}
close(fd);
return 0;
}
#include
#include
#include
#include
#include
#include
#include
//有名管道进程间通信
int main()
{
//access检测文件是否存在,F_OK,R_OK,W_OK,X_OK
if(access("/home/lsf/jincheng_course/myfifo",F_OK)==-1){//mufifo不存在则创建管道
//创建一个有名管道
int ret_fifo = mkfifo("/home/lsf/jincheng_course/myfifo",0777);
if(ret_fifo==-1){
perror("file exist");
}
}
//打开文件
int fd = open("/home/lsf/jincheng_course/myfifo",O_WRONLY);
if(fd==-1){
perror("open myfifo failed");
return -1;
}
char buf[128];
//写文件
while(1){
fgets(buf,sizeof(buf),stdin);
write(fd,buf,sizeof(buf)-1);
if(strcmp(buf,"bye\n")==0){//因为我们输入完bye后还会输入一个回车会被fgets读取到,所以为了避免错我们加一个回车
break;
}
}
close(fd);
return 0;
}
#include
#include
#include
#include
#include
#include
#include
#include
//自我实现日志服务器例程
int main()
{
//判断管道文件是否存在
if(access("/home/lsf/jincheng_course/logfifo",F_OK)==-1){//如果不存在
//创建有名管道文件
int ret_fifo = mkfifo("/home/lsf/jincheng_course/logfifo",0777);
if(ret_fifo==-1){
perror("file exist");
}
}
//打开管道文件
int fd = open("/home/lsf/jincheng_course/logfifo",O_WRONLY);
if(fd==-1){
perror("open logfifo failed");
return -1;
}
char buf[128];//定义缓冲区
// char tbuf[64];//定义时间缓冲区
int count = 0;//写30次不写了
while(1){
//获取进程号
int pid = getpid();
//获取时间方法一
// time_t current_time;
// struct tm* time_info;
// time(¤t_time);//获取时间
// time_info = localtime(¤t_time);//函数将时间信息转换为本地时间结构
// // 格式化当前时间为字符串
// strftime(tbuf, sizeof(tbuf), "%Y-%m-%d %H:%M:%S", time_info);
//获取时间方法二
time_t curTime;
sleep(1);
curTime++;
time(&curTime);
char* curData = ctime(&curTime);
//拼接时间和进程号
snprintf(buf,sizeof(buf),"this time:%s pid = %d\n",curData,pid);
//写文件
write(fd,buf,strlen(buf));
printf("%s\n",buf);
count++;
if(count==30){
break;
}
}
close(fd);
return 0;
}
#include
#include
#include
#include
#include
#include
#include
#include
//自我实现日志服务器例程
int main()
{
//判断管道文件是否存在
if(access("/home/lsf/jincheng_course/logfifo",F_OK)==-1){//如果不存在
//创建有名管道文件
int ret_fifo = mkfifo("/home/lsf/jincheng_course/logfifo",0777);
if(ret_fifo==-1){
perror("file exist");
}
}
//打开管道文件
int fd = open("/home/lsf/jincheng_course/logfifo",O_RDONLY);
if(fd==-1){
perror("open logfifo failed");
return -1;
}
//创建日志文件
int fd2 = open("/home/lsf/jincheng_course/sys_log.txt",O_RDWR | O_CREAT,0777);
if(fd2==-1){
perror("open sys_log.txt failed");
return -1;
}
char buf[128];//定义缓冲区
int count = 0;//读30次不读了
while(1){
//读出管道文件
memset(buf,0,sizeof(buf));//清空
read(fd,buf,sizeof(buf)-1);
printf("%s\n",buf);//打印
//写入日志文件
write(fd2,buf,strlen(buf));
count++;
if(count==30){
break;
}
}
close(fd);
return 0;
}