linuxC-进程间通信-有名管道fifo
- 格式:pdf
- 大小:632.06 KB
- 文档页数:7
c语言有名管道fifo管道的用法【C语言有名管道(FIFO管道)的用法】中括号为主题的文章【引言】C语言是一种广泛应用于系统软件开发的编程语言,拥有丰富的库函数和系统调用接口。
在C语言中,有名管道(也称为FIFO管道)是一种特殊的文件类型,用于实现不同进程之间的通信。
本文将一步一步详细介绍C语言有名管道(FIFO 管道)的用法,以帮助读者更好地理解和使用该功能。
【目录】一、什么是有名管道二、有名管道的创建三、有名管道的打开和关闭四、有名管道的读写操作五、有名管道的进程间通信六、有名管道的应用示例七、有名管道的优缺点八、总结【一、什么是有名管道】有名管道是一种特殊的文件类型,在文件系统中以文件的形式存在。
它是C语言用于进程间通信的一种方式,可以实现不同进程之间的数据传输。
有名管道是一种半双工的通信机制,允许一个进程写入数据到管道,同时另一个进程从管道中读取数据。
有名管道适用于在不相关的进程之间进行通信,特别是父子进程之间。
【二、有名管道的创建】要创建一个有名管道,首先需要使用C语言库函数mkfifo来创建一个文件节点(相当于管道的入口)。
mkfifo函数的原型如下:int mkfifo(const char *pathname, mode_t mode);其中,pathname代表要创建的有名管道的文件路径,mode用于设置管道的权限。
例如,以下代码会创建一个名为myfifo的有名管道:#include <sys/types.h>#include <sys/stat.h>int main() {mkfifo("myfifo", 0666);return 0;}运行该程序后,系统中将会被创建一个名为myfifo的有名管道。
【三、有名管道的打开和关闭】打开一个有名管道以进行读取和写入操作,可以使用C语言库函数open。
open 函数的原型如下:int open(const char *pathname, int flags);其中,pathname代表要打开的有名管道的文件路径,flags用于指定打开管道的方式(只读、只写、读写)。
网络与信息安全管理员(4级)试题一、单选题(共60题,每题1分,共60分)1、在Linux系统中,()通常称为FIFO。
A、无名管道B、有名管道C、文件管道D、命名管道正确答案:D2、WireShark软件安装时可选安装的WinPcap软件的作用是()。
A、提供包过滤能力B、提供GUI界面C、提供底层的抓包能力D、增强抓包结果的分析能力正确答案:C3、()是传输层以上实现两个异构系统互连的设备。
A、路由器B、网桥C、网关D、集线器正确答案:A4、()是指攻击者在非授权的情况下,对用户的信息进行修改,如修改电子交易的金额。
A、非法使用攻击B、拒绝服务攻击C、信息泄漏攻击D、完整性破坏攻击正确答案:D5、网络犯罪的人一般具有较高的专业水平体现了互联网信息内容安全犯罪()的特点。
A、犯罪手段提升B、犯罪后果严重化C、犯罪主体专业化D、犯罪手段隐蔽化正确答案:C6、下列关于Botnet说法错误的是()。
A、用Botnet发动DDoS攻击B、Botnet的显著特征是大量主机在用户不知情的情况下,被植入了C、拒绝服务攻击与Botnet网络结合后攻击能力大大削弱D、Botnet可以被用来传播垃圾邮件、窃取用户数据、监听网络和扩正确答案:C7、来自网络的拒绝服务攻击可以分为停止服务和消耗资源两类。
攻击特点不包括以下哪个()。
A、多源性、特征多变性B、攻击目标与攻击手段多样性C、开放性D、隐蔽性正确答案:C8、计算机病毒的特性包括()。
A、传播性、破坏性、寄生性B、传染性、破坏性、可植入性C、破坏性、隐蔽性、潜伏性D、自我复制性、隐蔽性、潜伏正确答案:C9、TCSEC标准将计算机系统分为()个等级、7个级别。
A、4B、5C、6D、7正确答案:A10、上网收集与被害人、被害单位有关的负面信息,并主动联系被害人、被害单位,以帮助删帖、“沉底”为由,向其索取财物的行为,构成()。
A、诈骗罪B、诽谤罪C、侮辱罪D、敲诈勒索罪正确答案:D11、TCP/IP参考模型的四个层次分别为()、网际层、传输层、应用层。
2011-06-08 21:45linux 管道 FIFO——写的很全,转来的pipe是Linux中最经典的进程间通信手段,在终端里通常用来组合命令,例如“ls -l|wc -l”。
它的作用很直观,就是使得前一个进程的输出作为后一个进程的输入,在概念上很符合“管道”的意思。
用管道实现“ls -l | wc -l”《情景分析》上有这个例子的代码,我觉得很适合用来了解管道。
这里假设终端对应的进程为PA,wc、ls是PA先后创建的两个子进程child_B与child_C。
代码简化后抄录如下:int main(){int pipefds[2], child_B, child_C;pipe(pipefds);if (!(child_B=fork()){ //先创建“读”的一端,它要关闭“写”的的一端close(pipefds[1]);close(0);dup2(pipefds[0], 0); //在执行系统调用execve后,child_B会释放0,1,2之外由父进程打开的文件,close(pipefds[0]); //所以要把pipefds[0]复制到标准输入对应的文件句柄0 execl("/usr/bin/wc", "-l", NULL);} //这里之后,A和B可以通过管道进行通信close(pipefds[0]);if (!(child_C=fork()){ //再创建“写”的一端,它要关闭“读”的的一端close(1);dup2(pipefds[1],1); //道理同前面close(pipefds[1]);execl("/bin/ls", "-1", NULL);} //这里之后,B和C可以通过管道进行通信close(pipefds[1]);wait4(child_B, NULL, 0, NULL);return 0;}FIFOFIFO就是命名管道,或有名管道。
linux管道fifo监听用法Linux管道(FIFO)监听用法Linux管道(FIFO)是一种特殊类型的文件,用于进程间通信。
它允许两个或多个进程在同时进行读写操作,实现数据传输和共享。
管道本身是一种单向的通道,数据只能在一个方向上流动。
本文将详细介绍Linux管道的监听用法,以帮助读者理解其工作原理和使用方法。
1. 创建FIFO管道:要使用管道进行通信,首先需要创建一个FIFO管道文件。
在Linux中,可以使用mkfifo命令创建一个FIFO文件,其语法格式如下:shellmkfifo [管道文件名]例如,要创建一个名为myfifo的管道文件,可以运行以下命令:shellmkfifo myfifo2. 打开FIFO管道:创建了FIFO管道文件后,进程需要打开该管道以进行数据的读写操作。
在Linux中,可以使用open系统调用在C语言程序中打开一个管道文件。
以下是open函数的原型:c#include <fcntl.h>int open(const char *pathname, int flags);其中,`pathname`是要打开的管道文件名,`flags`是打开文件的标志。
常见的标志有O_RDONLY(只读模式打开管道)、O_WRONLY(只写模式打开管道)和O_RDWR(读写模式打开管道)。
例如,在C语言程序中,要以只读模式打开myfifo管道文件,可以使用以下代码:cint fd = open("myfifo", O_RDONLY);3. 监听FIFO管道:打开管道后,进程就可以监听管道,等待其他进程向其写入数据。
在Linux 中,可以使用read函数从管道中读取数据。
以下是read函数的原型:c#include <unistd.h>ssize_t read(int fd, void *buf, size_t count);其中,`fd`是打开的管道文件的文件描述符,`buf`是接收数据的缓冲区,`count`是要读取的字节数。
Linux⽂件系统--简述⼏种⽂件类型 Linux 中⼀切皆为⽂件,⽂件类型也有多种,使⽤ ls -l 命令可以查看⽂件的属性,所显⽰结果的第⼀列的第⼀个字符⽤来表明该⽂件的⽂件类型,如下:1、普通⽂件 使⽤ ls -l 命令后,第⼀列第⼀个字符为 "-" 的⽂件为普通⽂件,如上图所⽰,普通⽂件⼀般为灰⾊字体,绿⾊字体的是可执⾏⽂件,红⾊字体的是压缩⽂件。
⽂件的权限: 以普通⽂件为例,使⽤ ls -l 命令,可以看到结果的第⼀列是 -rwxrwxrwx 的形式,其中第⼀个字符 "-" 表⽰这个⽂件为普通⽂件,它也可以是其他的字符,不同的字符代表不同类型的⽂件。
其后的⼀串字符表明了该⽂件的权限,其中:1)r 表明该⽂件具有可读权限,若该位置为 "-" ,则表明⽂件不可读;2)w 表明该⽂件具有写权限,若该位置为 "-" ,则表明⽂件不可写;3)x 表明该⽂件具有可执⾏权限,若该位置为 "-" ,则表明⽂件不具有可执⾏权限;4)第⼀个 rwx 表⽰该⽂件的所有者对该⽂件的权限;第⼆个 rwx 表⽰该⽂件所属组对该⽂件的权限;第三个 rwx 表⽰其他⽤户对该⽂件的权限。
创建⼀个普通⽂件: 可以使⽤ touch 命令来创建⼀个⽂件:touch newfile删除⼀个普通⽂件: 可以使⽤ rm 命令来删除⼀个⽂件:rm newfile2、⽬录⽂件 Linux 中的⽬录也是⽂件,⽬录⽂件中保存着该⽬录下其他⽂件的 inode 号和⽂件名等信息,⽬录⽂件中的每个数据项都是指向某个⽂件 inode 号的链接,删除⽂件名就等于删除与之对应的链接。
⽬录⽂件的字体颜⾊是蓝⾊,使⽤ ls -l 命令查看,第⼀个字符为"d"(directory)。
⽬录⽂件的权限:1)r 表明该⽬录⽂件具有可读权限,即可以使⽤ ls 命令查看该⽬录的存储情况;2)w 表明该⽬录⽂件具有写权限,即可以往该⽬录下添加、修改、删除⽂件;3)x 表明该⽬录⽂件具有可执⾏⽂件,即可以使⽤ cd 命令进⼊到该⽬录下。
关于C语⾔进程操作关于C语⾔进程操作Linux标准库 <unistd.h>符号常量NULL // Null pointerSEEK_CUR // Set file offset to current plus offset.SEEK_END // Set file offset to EOF plus offset.SEEK_SET // Set file offset to offset.是POSIX标准定义的unix类系统定义符号常量的头⽂件,包含了许多UNIX系统服务的函数原型,例如read函数、write函数和getpid函数。
unistd.h在unix中类似于window中的windows.h。
#ifdef WIN32#include <windows.h>#else#include <unistd.h>#endif函数原型ssize_t read(int, void *, size_t);int unlink(const char *);ssize_t write(int, const void *, size_t);int usleep(useconds_t);unsigned sleep(unsigned);int access(const char *, int);unsigned alarm(unsigned);int chdir(const char *);int chown(const char *, uid_t, gid_t);int close(int);size_t confstr(int, char *, size_t);void _exit(int);pid_t fork(void);关于管道pipe管道的概念管道是⼀种最基本的IPC机制,作⽤于有⾎缘关系的进程之间,完成数据传递。
调⽤pipe系统函数即可创建⼀个管道。
有如下特质:其本质是⼀个伪⽂件(实为内核缓冲区)由两个⽂件描述符引⽤,⼀个表⽰读端,⼀个表⽰写端。
Linux C 一些函数所属的头文件在编写程序时,有时总是不记得所使用的函数在哪个库函数中。
现在先把自己以前经常用到的函数头文件总结一下。
有不对的地方还请指教。
1,系统调用文件的操作函数#inlclude <fcntl.h>int open(char *name,int how) 第二个参数,O_RDONLY O_WRONL Y O_RDWR O_CREAT #include <unistd.h>int close(int fd)size_t read(int fd,void *buf, size_t count)size_t write(int fd,const void *buf,size_t count)sleep(1) 系统睡眠一秒钟,最小单位为一秒。
#define msleep(x) usleep(x*1000)msleep(500); 系统睡眠0.5秒#include <stdio.h>perror("会出现错误的函数名")#include <string.h>char *strerror(int errnum) 依据错误代码errnum来查找错误原因字符串char *strcpy(char *dest,const char *src)int strcmp(char *s1,const char *s2) s1若等于s2的值则返回0值int strncmp(char *s1,const char *s2,int n) 前n个字符串比较2,进程控制函数#include <unistd.h>pid_t fork(void) 子进程中返回0 父进程中返回子进程ID 出错返回-1pid_t getpid(void) pid_t getppid(void)pid_t vfork(void)exec函数族进程pid 的类型为pid_t 类型,它包含于#include <sys/types.h> 若定义一个进程pid变量,则需要包含此头文件exit(n)结束进程父进程可以由wait函数来获得子进程结束装状态。
linux编程之pipe()函数详解管道是⼀种把两个进程之间的标准输⼊和标准输出连接起来的机制,从⽽提供⼀种让多个进程间通信的⽅法,当进程创建管道时,每次都需要提供两个⽂件描述符来操作管道。
其中⼀个对管道进⾏写操作,另⼀个对管道进⾏读操作。
对管道的读写与⼀般的IO系统函数⼀致,使⽤write()函数写⼊数据,使⽤read()读出数据。
#include<unistd.h>int pipe(int filedes[2]);返回值:成功,返回0,否则返回-1。
参数数组包含pipe使⽤的两个⽂件的描述符。
fd[0]:读管道,fd[1]:写管道。
必须在fork()中调⽤pipe(),否则⼦进程不会继承⽂件描述符。
两个进程不共享祖先进程,就不能使⽤pipe。
但是可以使⽤命名管道。
当管道进⾏写⼊操作的时候,如果写⼊的数据⼩于128K则是⾮原⼦的,如果⼤于128K字节,缓冲区的数据将被连续地写⼊管道,直到全部数据写完为⽌,如果没有进程读取数据,则将⼀直阻塞,如下:在上例程序中,⼦进程⼀次性写⼊128K数据,当⽗进程将全部数据读取完毕的时候,⼦进程的write()函数才结束阻塞并且返回写⼊信息。
命名管道FIFO管道最⼤的劣势就是没有名字,只能⽤于有⼀个共同祖先进程的各个进程之间。
FIFO代表先进先出,单它是⼀个单向数据流,也就是半双⼯,和管道不同的是:每个FIFO都有⼀个路径与之关联,从⽽允许⽆亲缘关系的进程访问。
#include <sys/types.h>#include <sys/stat.h>int mkfifo(const char *pathname, mode_t mode);这⾥pathname是路径名,mode是sys/stat.h⾥⾯定义的创建⽂件的权限.有亲缘关系进程间的fifo的例⼦/** 有亲缘关系的进程间的fifo的使⽤* fifo 使⽤的简单例⼦*/#include "../all.h"#define FIFO_PATH "/tmp/hover_fifo"voiddo_sig(int signo){if (signo == SIGCHLD)while (waitpid(-1, NULL, WNOHANG) > 0);}intmain(void){int ret;int fdr, fdw;pid_t pid;char words[10] = "123456789";char buf[10] = {'\0'};// 创建它,若存在则不算是错误,// 若想修改其属性需要先打开得到fd,然后⽤fcntl来获取属性,然后设置属性.if (((ret = mkfifo(FIFO_PATH, FILE_MODE)) == -1)&& (errno != EEXIST))perr_exit("mkfifo()");fprintf(stderr, "fifo : %s created successfully!\n", FIFO_PATH);signal(SIGCHLD, do_sig);pid = fork();if (pid == 0) { // childif ((fdr = open(FIFO_PATH, O_WRONLY)) < 0) // 打开fifo⽤来写perr_exit("open()");sleep(2);// 写⼊数据if (write(fdr, words, sizeof(words)) != sizeof(words))perr_exit("write");fprintf(stderr, "child write : %s\n", words);close(fdw);} else if (pid > 0) { // parentif ((fdr = open(FIFO_PATH, O_RDONLY)) < 0) // 打开fifo⽤来读perr_exit("open()");fprintf(stderr, "I father read, waiting for child ...\n");if (read(fdr, buf, 9) != 9) //读数据perr_exit("read");fprintf(stderr, "father get buf : %s\n", buf);close(fdr);}// 到这⾥fifo管道并没有被删除,必须⼿动调⽤函数unlink或remove删除.return 0;}从例⼦上可以看出使⽤fifo时需要注意:*fifo管道是先调⽤mkfifo创建,然后再⽤open打开得到fd来使⽤.*在打开fifo时要注意,它是半双⼯的的,⼀般不能使⽤O_RDWR打开,⽽只能⽤只读或只写打开.fifo可以⽤在⾮亲缘关系的进程间,⽽它的真正⽤途是在服务器和客户端之间. 由于它是半双⼯的所以,如果要进⾏客户端和服务器双⽅的通信的话,每个⽅向都必须建⽴两个管道,⼀个⽤于读,⼀个⽤于写.下⾯是⼀个服务器,对多个客户端的fifo的例⼦:server 端的例⼦:/** FIFO server*/#include "all.h"intmain(void){int fdw, fdw2;int fdr;char clt_path[PATH_LEN] = {'\0'};char buf[MAX_LINE] = {'\0'};char *p;int n;if (mkfifo(FIFO_SVR, FILE_MODE) == -1 && errno != EEXIST)perr_exit("mkfifo()");if ((fdr = open(FIFO_SVR, O_RDONLY)) < 0)perr_exit("open()");/** 根据fifo的创建规则, 若从⼀个空管道或fifo读,* ⽽在读之前管道或fifo有打开来写的操作, 那么读操作将会阻塞* 直到管道或fifo不打开来读, 或管道或fifo中有数据为⽌.** 这⾥,我们的fifo本来是打开⽤来读的,但是为了,read不返回0,* 让每次client端读完都阻塞在fifo上,我们⼜打开⼀次来读.* 见unpv2 charper 4.7*/if ((fdw2 = open(FIFO_SVR, O_WRONLY)) < 0)fprintf(stderr, "open()");while (1) {/* read client fifo path from FIFO_SVR *//* 这⾥由于FIFO_SVR有打开来写的操作,所以当管道没有数据时,* read会阻塞,⽽不是返回0.*/if (read(fdr, clt_path, PATH_LEN) < 0) {fprintf(stderr, "read fifo client path error : %s\n", strerror(errno));break;}if ((p = strstr(clt_path, "\r\n")) == NULL) {fprintf(stderr, "clt_path error: %s\n", clt_path);break;}*p = '\0';DBG("clt_path", clt_path);if (access(clt_path, W_OK) == -1) { // client fifo ok, but no permissionperror("access()");continue;}/* open client fifo for write */if ((fdw = open(clt_path, O_WRONLY)) < 0) {perror("open()");continue;}if ((n = read(fdr, buf, WORDS_LEN)) > 0) { /* read server words is ok */printf("server read words : %s\n", buf);buf[n] = '\0';write(fdw, buf, strlen(buf));}}close(fdw);unlink(FIFO_SVR);exit(0);}客户端的例⼦:/** Fifo client**/#include "all.h"intmain(void){int fdr, fdw;pid_t pid;char clt_path[PATH_LEN] = {'\0'};char buf[MAX_LINE] = {'\0'};char buf_path[MAX_LINE] = {'\0'};snprintf(clt_path, PATH_LEN, FIFO_CLT_FMT, (long)getpid());DBG("clt_path1 = ", clt_path);snprintf(buf_path, PATH_LEN, "%s\r\n", clt_path);if (mkfifo(clt_path, FILE_MODE) == -1 && errno != EEXIST)perr_exit("mkfifo()");/* client open clt_path for read* open server for write*/if ((fdw = open(FIFO_SVR, O_WRONLY)) < 0)perr_exit("open()");/* write my fifo path to server */if (write(fdw, buf_path, PATH_LEN) != PATH_LEN)perr_exit("write()");if (write(fdw, WORDS, WORDS_LEN) < 0) /* write words to fifo server */perr_exit("error");if ((fdr = open(clt_path, O_RDONLY)) < 0)perr_exit("open()");if (read(fdr, buf, WORDS_LEN) > 0) { /* read reply from fifo server */buf[WORDS_LEN] = '\0';printf("server said : %s\n", buf);}close(fdr);unlink(clt_path);exit(0);}以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。
【linux】下的mkfifo命令和【C语⾔】中的mkfifo函数# mkfifo myfifo# ping >> myfifo另开⼀个终端:# cat myfifo看到效果了吧mkfifo 命令⽤途制作先进先出(FIFO)特别⽂件。
语法mkfifo [ -m Mode ] File …描述根据指定的顺序,mkfifo 命令创建由 File 参数指定的 FIFO 特别⽂件。
如果没有指定 -m Mode 标志,则 FIFO ⽂件的⽂件⽅式是通过⽂件⽅式创建所修改的包含 OR 的 S_IRUSR、S_IWUSR、S_IRGRP、S_IWGRP、S_IROTH 和 S_IWOTH 许可权的⼀位宽度(请参阅 umask 命令)。
mkfifo 命令与 mkfifo ⼦例程运⾏相似。
标志-m Mode 设置新创建的 FIFO ⽂件的⽂件许可权位的值为指定的⽅式值。
Mode 变量与为 chmod 命令定义的⽅式操作数相同。
如果使⽤了字符 +(加号)和 -(减号),则它们是相对于初始值 a=rw 来解释的(即具有许可权 rw-rw-rw-)。
退出状态这条命令返回以下退出值:0 成功创建所有指定的 FIFO 特别⽂件。
>0 发⽣错误。
⽰例1. 要使⽤许可权 prw-r–r– 创建 FIFO 特别⽂件,请输⼊:mkfifo -m 644 /tmp/myfifo此命令使⽤所有者的读/写许可权以及组和其他⽤户的读许可权来创建 /tmp/myfifo ⽂件。
2. 使⽤ -(减号)操作符创建⼀个 FIFO 特别⽂件以设置 prw-r—– 许可权,请输⼊:mkfifo -m g-w,o-rw /tmp/fifo2此命令创建 /tmp/fifo2 ⽂件,删除组的写权限和其他⽤户的所有许可权。
注:如果多于⼀个的⽂件是⽤ -(减号)操作符创建的,那么⽤顿号分隔每个⽅式说明符,中间不⽤空格。
⽂件/usr/bin/mkfifo 包含 mkfifo 命令。
实验三进程的管道通信一、实验目的(1)了解什么是管道(2)熟悉UNIX/LINUX支持的管道通信方式二、实验学时4学时三、实验内容编写程序实现进程的管道通信。
用系统调用pipe( )建立一管道,二个子进程P1和P2分别向管道各写一句话:Child 1 is sending a message!Child 2 is sending a message!父进程从管道中读出二个来自子进程的信息并显示(要求先接收P1,后P2)。
四、实验指导一、什么是管道UNIX系统在OS的发展上,最重要的贡献之一便是该系统首创了管道(pipe)。
这也是UNIX系统的一大特色。
所谓管道,是指能够连接一个写进程和一个读进程的、并允许它们以生产者—消费者方式进行通信的一个共享文件,又称为pipe文件。
由写进程从管道的写入端(句柄1)将数据写入管道,而读进程则从管道的读出端(句柄0)读出数据。
1、有名管道一个可以在文件系统中长期存在的、具有路径名的文件。
用系统调用mknod( )建立。
它克服无名管道使用上的局限性,可让更多的进程也能利用管道进行通信。
因而其它进程可以知道它的存在,并能利用路径名来访问该文件。
对有名管道的访问方式与访问其他文件一样,需先用open( )打开。
2、无名管道一个临时文件。
利用pipe( )建立起来的无名文件(无路径名)。
只用该系统调用所返回的文件描述符来标识该文件,故只有调用pipe( )的进程及其子孙进程才能识别此文件描述符,才能利用该文件(管道)进行通信。
当这些进程不再使用此管道时,核心收回其索引结点。
二种管道的读写方式是相同的,本文只讲无名管道。
3、pipe文件的建立分配磁盘和内存索引结点、为读进程分配文件表项、为写进程分配文件表项、分配用户文件描述符4、读/写进程互斥内核为地址设置一个读指针和一个写指针,按先进先出顺序读、写。
为使读、写进程互斥地访问pipe文件,需使各进程互斥地访问pipe文件索引结点中的直接地址项。
FIFO管道求助编辑百科名片本词条主要介绍 FIFO管道FIFO也称为有名管道,它是一种文件类型,在文件系统中可以看到。
程序中可以查看文件stat结构中st_mode成员的值来判断文件是否是FIFO文件。
创建一个FIFO文件类似于创建文件,FIFO文件就像普通文件一样。
FIFO的概念FIFO中可以很好地解决在无关进程间数据交换的要求,并且由于它们是存在于文件系统中的,这也提供了一种比匿名管道更持久稳定的通信办法。
FIFO的通信方式类似于在进程中使用文件来传输数据,只不过FIFO类型文件同时具有管道的特性。
在数据读出时,FIFO管道中同时清除数据。
在shell中mkfifo命令可以建立有名管道,下面通过一个实例来帮助读者理解FIFO。
mkfifo命令的帮助手册如下所示:mkfifo [option] name...其中option选项中可以选择要创建FIFO的模式,使用形式为-m mode,这里mode指出将要创建FIFO的八进制模式,注意,这里新创建的FIFO会像普通文件一样受到创建进程的umask修正。
在shell中输入命令如下:$mkfifo –m 600 fifocat$cat < fifocat$./recat >fifocat$./recat >fifocat#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <fcntl.h>#include <limits.h>#define BUFES PIPE_BUFint main ( void ){FILE *fp;char * cmd = "cat file1"; /*shell 命令*/char * buf[BUFSZ];.........pclose ( fp ) ; /*关闭管道*/exit (0) ;}$_以上实例使用系统命令mkfifo创建FIFO类型文件fifocat,并通过14.2.4节的程序recat来读取文件recat.c,将程序的标准输出从定向到fifocat中,再使用命令cat从fifocat读出数据。
Linux环境进程间通信(一):管道及有名管道管道及有名管道在本系列序中作者概述了linux进程间通信的几种主要手段。
其中管道和有名管道是最早的进程间通信机制之一,管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信。
认清管道和有名管道的读写规则是在程序中应用它们的关键,本文在详细讨论了管道和有名管道的通信机制的基础上,用实例对其读写规则进行了程序验证,这样做有利于增强读者对读写规则的感性认识,同时也提供了应用范例。
1、管道概述及相关api应用1.1管道相关的关键概念管道就是linux积极支持的最初unixipc形式之一,具备以下特点:管道就是半双工的,数据就可以向一个方向流动;须要双方通信时,须要创建起至两个管道;就可以用作父子进程或者兄弟进程之间(具备亲缘关系的进程);单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且只存在与内存中。
数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出。
写入的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据。
1.2管道的建立:#includeintpipe(intfd[2])该函数建立的管道的两端处在一个进程中间,在实际应用领域中没太小意义,因此,一个进程在由pipe()建立管道后,通常再fork一个子进程,然后通过管道同时实现父子进程间的通信(因此也不难面世,只要两个进程中存有亲缘关系,这里的亲缘关系所指的就是具备共同的祖先,都可以使用管道方式去展开通信)。
1.3管道的读取规则:管道两端可分别用描述字fd[0]以及fd[1]来描述,需要注意的是,管道的两端是固定了任务的。
即一端只能用于读,由描述字fd[0]表示,称其为管道读端;另一端则只能用于写,由描述字fd[1]来表示,称其为管道写端。
进程间通信—有名管道
◦fifo简介
无名管道,它只能用于具有亲缘关系的进程之间,这就大大地限制了管道的使用。
有名管道的出现突破了这种限制,它可以使互不相关的两个进程实现彼此通信。
该管道可以通过路径名来指出,并且在文件系统中是可见的。
在建立了管道之后,两个进程就可以把它当作普通文件一样进行读写操作,使用非常方便。
FIFO 是严格地遵循先进先出规则的,对管道及 FIFO 的读总是从开始处返回数据,对它们的写则把数据添加到末尾,它们不支持如 lseek()等文件定位操作。
有名管道的创建可以使用函数 mkfifo(),该函数类似文件中的 open()操作,可以指定管道的路径和打开的模式。
进程通过文件IO来操作有名管道,有名管道创建之后,任何进程都可以访问。
◦fifo打开方式
在创建管道成功之后,就可以使用open()、read()和write()这些函数了。
与普通文件的开发设置一样,对于为读而打开的管道可在open()中设置
O_RDONLY,对于为写而打开的管道可在open()中设置O_WRONLY。
1.如果打开的时候是,是以只读方式(O_RDONLY)打开的,则open返回
的文件描述符fd是只读的。
2.如果打开的时候是,是以只写方式(O_WRONLY)打开的,则open返回的
文件描述符fd是只写的
3.如果打开的时候是,是以读写方式(O_RDWR)打开的,则open返回的文
件描述符fd是读写的
◦fifo读写特性
由于普通文件的读写时不会出现阻塞问题,而在管道的读写中却有阻塞的可能,这里的非阻塞标志可以
在open()函数中设定为O_NONBLOCK。
下面分别对阻塞打开和非阻塞打开的读写进行讨论。
(1)对于读进程。
•若该管道是阻塞打开,且当前FIFO内没有数据,则对读进程而言将一直阻塞到有数据写入。
•若该管道是非阻塞打开,则不论FIFO内是否有数据,读进程都会立即执行读操作。
即如果FIFO内没有数据,则读函数将立刻返回0。
(2)对于写进程。
•若该管道是阻塞打开,则写操作将一直阻塞到数据可以被写入。
•若该管道是非阻塞打开而不能写入全部数据,则读操作进行部分写入或者调用失败。
◦fifo创建函数
mkfifo()函数格式
表8.4列出了mkfifo()函数的语法要点。
函数语法要点
表8.4mkfifo()
FIFO
相关的出错信息
◦fifo创建终端命令
用户还可以在命令行使用“mknod 管道名 p”来创建有名管道。
还可以运用mkfifo 有名管道名 创建文件
命令mkfifo和有名管道函数创建一样。
◦典型的fifo模型
C/S模型
◦fifo示例
第一个文件create_fifo.c主要是创建一个管道文件,也可以用mkfifo命令来创建一个管道。
管道创建好之后可以在文件系统中看到,同时也可以看到文件的大小为0。
create_fifo.c
创建好之后的运行效果。
下面的程序要运用到否创建的这个管道文件。
read_fifo.c这是读取管道,从管道中读取文件。
write_fifo.c
程序的运行的结果如下:。