理解代码:
/** suck 端简单实现 */ #include<stdio.h> #include<unistd.h> #include<string.h> #include<sys/select.h> #include<fcntl.h>//读取方式宏定义 #include<sys/stat.h>//用户权限宏定义 #include<time.h> int main(){ int i,rfd,wfd,len=0,fd_in; char str[32]; int flag,stdinflag; //a file describe set fd_set write_fd,read_fd; struct timeval wait_time; //create and give power mkfifo("fifo1",S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH); mkfifo("fifo2",S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH); //这里需要注意打开FIFO读端会产生阻塞,直到它的写端打开 wfd=open("fifo1",O_WRONLY); rfd=open("fifo2",O_RDONLY); if(rfd<=0||wfd<=0) return 0; printf("suck client!\n"); while(1){ FD_ZERO(&read_fd);//初始化文件描述符集合中的各个文件描述符 FD_SET(rfd,&read_fd);//管道fifo1的读端文件描述符添加到文件描述符集合 FD_SET(fileno(stdin),&read_fd);//将标准输入文件描述符添加到集合 wait_time.tv_sec=5;//设置检测时间 wait_time.tv_usec=0;//应该是微秒的意思 memset(str,0,sizeof(str)); //select检测集合中是否有可读的东西,检测时间为5m,超时或错误则continue if(i=select(rfd+1,&read_fd,NULL,NULL,&wait_time)<=0) continue; //memset检测时会将没有内容的文件描述符去除 //如果rfd即管道内有可读内容则执行 if(FD_ISSET(rfd,&read_fd)){ read(rfd,str,sizeof(str)); printf("===============\n"); printf("message from dog:%s\n",str); } //如果键盘有输入 if(FD_ISSET(fileno(stdin),&read_fd)){ printf("==========\n"); fgets(str,sizeof(str),stdin); len=write(wfd,str,strlen(str)); } } close(rfd); close(wfd); return 0; } /** dog端简单实现 */ #include<stdio.h> #include<string.h> #include<sys/stat.h> #include<unistd.h> #include<fcntl.h> #include<time.h> #include<sys/select.h> int main(){ int i,rfd,wfd,len=0,fd_in; char str[32]; int flag,stdinflag; fd_set read_fd,write_fd; struct timeval wait_time; mkfifo("fifo1",S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH); mkfifo("fifo2",S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH); rfd=open("fifo1",O_RDONLY); wfd=open("fifo2",O_WRONLY); if(rfd<=0||wfd<=0) return 0; printf("dog client!\n"); while(1){ FD_ZERO(&read_fd); FD_SET(rfd,&read_fd); FD_SET(fileno(stdin),&read_fd); wait_time.tv_sec=5; wait_time.tv_usec=0; memset(str,0,sizeof(str)); if(i=select(wfd+1,&read_fd,NULL,NULL,&wait_time)<=0) continue; if(FD_ISSET(rfd,&read_fd)){ read(rfd,str,sizeof(str)); printf("==============\n"); printf("message from suck:%s\n",str); } if(FD_ISSET(fileno(stdin),&read_fd)){ printf("===============\n"); fgets(str,sizeof(str),stdin); len=write(wfd,str,strlen(str)); } } close(rfd); close(wfd); return 0; }运行结果:
wfd=open("fifo1",O_WRONLY); rfd=open("fifo2",O_RDONLY);
rfd=open("fifo1",O_RDONLY); wfd=open("fifo2",O_WRONLY);
在阻塞模式下,FIFO只有在读写端同时打开时才会返回,否则会一直阻塞。所以fifo1和fifo2顺序不能一个在前一个在后,如果一前一后会导致程序1和2都卡在等另外的端口打开。这好像是产生死锁的四个必要条件中的,循环等待条件
互斥条件:资源是独占的且排他使用,进程互斥使用资源,即任意时刻一个资源只能给一个进程使用,其他进程若申请一个资源,而该资源被另一进程占有时,则申请者等待直到资源被占有者释放。不可剥夺条件:进程所获得的资源在未使用完毕之前,不被其他进程强行剥夺,而只能由获得该资源的进程资源释放。请求和保持条件:进程每次申请它所需要的一部分资源,在申请新的资源的同时,继续占用已分配到的资源。循环等待条件 在发生死锁时必然存在一个进程等待队列{P1,P2,…,Pn},其中P1等待P2占有的资源,P2等待P3占有的资源,…,Pn等待P1占有的资源,形成一个进程等待环路,环路中每一个进程所占有的资源同时被另一个申请,也就是前一个进程占有后一个进程所深情地资源。 以上给出了导致死锁的四个必要条件,只要系统发生死锁则以上四个条件至少有一个成立。事实上循环等待的成立蕴含了前三个条件的成立,似乎没有必要列出然而考虑这些条件对死锁的预防是有利的,因为可以通过破坏四个条件中的任何一个来预防死锁的发生。里面主要的函数用法可以自行百度Google,也可参考:https://blog.csdn.net/cstarbl/article/details/7645298