Linux进程通信:命名管道FIFO小结
linux 实验五 命名管道实验

实验五 命名管道实验
1. 研究mkfifo 命令,在当前目录下创建一个myfifo 的命名管道。
(1)程序流程图:
(2)运行结果:
2、用mkfifo ()函数实现相同的功能。
(1)程序流程图:
(2)程序源代码:
/*mk_fifo.c*/ 终端中输入:
mkfifo
fifo_channel 用ls 命令查看当前目录是否产生了名为fifo_channel 的管道。
创建fifo 文件用的是函数mkfifo() mode 用来简历文件的权限,该函数成功则返回0,失败时返回-1,并且设置errno.
(3)运行结果:
3、编写一个服务器程序server.c ,实现从管道myfifo 中读取内容,并在终端中显示出来。
打开一个命令行终端,运行server ,然后打开另一个命令行终端,使用“cp 文件1 myfifo ”命令把文件1的内容输出到myfifo ,测试server.c 的功能。
(1)程序流程图:
(2)程序源代码: 创建管道,打开
管道,读出数据 利用命令cp ,把a 的内容复制到管道中
(3)运行结果:
4、编写客户机程序,实现把指定文件输出到myfifo的功能,从而实现和服务器程序的通信。
测试该程序的功能。
(1)程序流程图:基本同3,就不再画了。
(2)程序源代码:
/*server2.c*/
(3)实验结果:。
c语言有名管道fifo管道的用法

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用于指定打开管道的方式(只读、只写、读写)。
命名管道FIFO和mkfifo函数

命名管道FIFO和mkfifo函数进程间通信必须通过内核提供的通道,⽽且必须有⼀种办法在进程中标识内核提供的某个通道,前⾯讲过的是⽤打开的⽂件描述符来标识的。
如果要互相通信的⼏个进程没有从公共祖先那⾥继承⽂件描述符,它们怎么通信呢?内核提供⼀条通道不成问题,问题是如何标识这条通道才能使各进程都可以访问它?⽂件系统中的路径名是全局的,各进程都可以访问,因此可以⽤⽂件系统中的路径名来标识⼀个IPC通道。
FIFO和UNIX Domain Socket这两种IPC机制都是利⽤⽂件系统中的特殊⽂件来标识的。
FIFO⽂件在磁盘上没有数据块,仅⽤来标识内核中的⼀条通道,如 prw-rw-r-- 1 simba simba 0 May 21 10:13 p2,⽂件类型标识为p表⽰FIFO,⽂件⼤⼩为0。
各进程可以打开这个⽂件进⾏read/write,实际上是在读写内核通道(根本原因在于这个file结构体所指向的read、write函数和常规⽂件不⼀样),这样就实现了进程间通信。
UNIX Domain Socket和FIFO的原理类似,也需要⼀个特殊的socket⽂件来标识内核中的通道,例如/run⽬录下有很多系统服务的socket⽂件:srw-rw-rw- 1 root root 0 May 21 09:59 acpid.socket....................⽂件类型s表⽰socket,这些⽂件在磁盘上也没有数据块。
⼀、命名管道(FIFO)匿名管道应⽤的⼀个限制就是只能在具有共同祖先(具有亲缘关系)的进程间通信。
如果我们想在不相关的进程之间交换数据,可以使⽤FIFO⽂件来做这项⼯作,它经常被称为命名管道。
命名管道可以从命令⾏上创建,命令⾏⽅法是使⽤下⾯这个命令:$ mkfifo filename命名管道也可以从程序⾥创建,相关函数有:int mkfifo(const char *filename,mode_t mode);⼆、命名管道和匿名管道匿名管道由pipe函数创建并打开。
无名管道和有名管道区别

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进程管理实验心得

linux进程管理实验心得在操作系统课程中,我们进行了一系列关于Linux进程管理的实验。
通过这些实验,我对Linux进程管理有了更深入的理解,并且学到了很多有关进程管理的知识和技巧。
在这篇文章中,我将分享我的实验心得和体会。
首先,我学会了如何创建和终止进程。
在实验中,我们使用了fork()函数来创建子进程,并使用exec()函数来加载新的程序。
这样,我们可以在一个进程中创建多个子进程,并且每个子进程可以执行不同的任务。
而通过调用exit()函数,我们可以终止一个进程的执行。
这些操作让我更加清楚地了解了进程的创建和终止过程。
其次,我学会了如何管理进程的优先级。
在Linux中,每个进程都有一个优先级,用于决定进程在CPU上执行的顺序。
通过使用nice命令,我们可以为进程设置不同的优先级。
较高的优先级意味着进程将更频繁地获得CPU时间片,从而提高了进程的执行效率。
这对于提高系统的整体性能非常重要。
此外,我还学会了如何监控和调试进程。
在实验中,我们使用了ps命令来查看当前系统中正在运行的进程。
通过查看进程的状态和资源使用情况,我们可以了解到系统的运行状况。
而使用top命令,则可以实时地监控进程的运行情况。
此外,我们还学会了使用gdb调试器来调试进程。
通过设置断点和观察变量的值,我们可以找到程序中的错误并进行修复。
最后,我认识到进程管理是操作系统中非常重要的一部分。
一个好的进程管理系统可以提高系统的性能和稳定性。
通过合理地管理进程的创建、终止和调度,可以使系统更加高效地利用资源,并且能够更好地响应用户的需求。
因此,学习和掌握进程管理技术对于成为一名优秀的系统管理员或开发人员来说是非常重要的。
通过这些实验,我不仅学到了很多关于Linux进程管理的知识,还提高了自己的实践能力和问题解决能力。
在实验过程中,我遇到了各种各样的问题,但通过查阅资料、与同学讨论和不断尝试,我最终成功地解决了这些问题。
这让我更加自信地面对未来的挑战。
你不知道的Linux有名管道(FIFO)的阻塞和非阻塞读写

你不知道的Linux有名管道(FIFO)的阻塞和非阻塞读写有名管道的读写有阻塞和非阻塞两种,可以在open()时指定,下面我们对各种情况进行一些讨论。
//写进程#include #include #include #include #include #include #define FIFO_NAME "/tmp/myfifo"main(){int fd;char w_buf[50];int w_num;// 若fifo已存在,则直接使用,否则创建它if((mkfifo(FIFO_NAME,0777)#include #include #include #define FIFO_NAME "/tmp/myfifo"main(){char r_buf[50];int fd;int r_num;// 若fifo已存在,则直接使用,否则创建它if((mkfifo(FIFO_NAME,0777)字符串,再将其写入fifo,直到输入"exit"为止r_num=read(fd,r_buf,6);printf(" %d bytes read:%s\n",r_num,r_buf);unlink(FIFO_NAME);//删除fifo} 1.写进程阻塞,读进程阻塞。
先运行写进程(被阻塞),再运行读进程,一切正常。
先运行读进程(被阻塞),再运行写进程,一切正常。
2.写进程阻塞,读进程非阻塞。
就改一句代码fd=open(FIFO_NAME,O_RDONLY | O_NONBLOCK),下面类似。
先运行写进程(被阻塞),再运行读进程,一切正常。
先运行读进程,程序直接崩掉(Segmentation fault (core dumped)),想想也挺自然的,没东西你还要读,而且不愿等。
3.写进程非阻塞,读进程阻塞。
先运行写进程,open调用将返回-1,打开失败。
简述linux中进程间各种通信方式特点

简述linux中进程间各种通信方式特点Linux中进程间通信方式有多种,包括管道,命名管道,消息队列,信号量,共享内存和套接字。
每种通信方式都有自己的特点和适用场景。
一、管道1. 特点:- 管道是最简单的进程间通信方式之一,只能用于具有父子关系的进程间通信。
- 管道是一个单向通道,数据只能在一个方向上流动。
- 管道的容量有限,在写度满之前,读进程阻塞;在读度空之前,写进程阻塞。
2. 使用场景:- 父子进程之间需要进行简单的数据传输。
二、命名管道1. 特点:- 命名管道是一种特殊类型的文件,可以实现不相关进程的通信。
- 命名管道是半双工的,只能在一个方向上传输数据。
- 命名管道是顺序读写的,进程可以按照顺序读取其中的数据。
2. 使用场景:- 不相关的进程需要进行数据传输。
- 需要按照顺序进行传输的场景。
三、消息队列1. 特点:- 消息队列是一组消息的链表,具有特定的格式和标识符。
- 消息队列独立于发送和接收进程的生命周期,可以实现不相关进程间的通信。
- 消息队列可以根据优先级进行消息的传输。
2. 使用场景:- 需要实现进程间相对复杂的数据传输。
- 数据传输具有优先级。
四、信号量1. 特点:- 信号量是一个计数器,用于实现多个进程之间的互斥和同步。
- 信号量有一个整数值,只能通过定义的操作进行访问。
- 信号量可以用于控制临界区的访问次数。
2. 使用场景:- 多个进程需要共享公共资源。
- 需要进行互斥和同步操作。
五、共享内存1. 特点:- 共享内存是一块可以被多个进程共同访问的内存区域。
- 共享内存是最快的进程间通信方式,因为数据不需要在进程之间拷贝。
- 共享内存需要通过同步机制(如信号量)进行互斥访问。
2. 使用场景:- 需要高效地进行大量数据传输。
- 数据读写频繁,需要最小化数据拷贝的开销。
六、套接字1. 特点:- 套接字是一种网络编程中常用的进程间通信方式。
- 套接字支持不同主机上的进程进行通信。
Linux命令高级技巧通过mknod命令创建特殊文件和设备节点

Linux命令高级技巧通过mknod命令创建特殊文件和设备节点Linux命令高级技巧:通过mknod命令创建特殊文件和设备节点Linux作为一种开源操作系统,广泛用于服务器、嵌入式系统等领域,因其稳定性和灵活性备受青睐。
使用Linux操作系统,掌握一些高级命令技巧可以更好地发挥其功能。
本文将介绍如何使用mknod命令创建特殊文件和设备节点,以提升Linux系统的应用。
一、mknod命令概述mknod命令是Linux系统中用于创建特殊文件和设备节点的命令。
特殊文件和设备节点是Linux系统中用于访问硬件设备或其他特殊操作的接口,如磁盘、串口等。
通过mknod命令,用户可以手动创建这些接口,以满足特定需求。
二、创建块设备节点在Linux系统中,块设备是一种按固定大小的数据块进行读写的设备,常见的块设备有硬盘、USB闪存等。
通过mknod命令可以创建块设备节点,步骤如下:1. 以root身份登录Linux系统。
2. 打开终端,并执行以下命令:```sudo mknod /dev/mydevice b major-number minor-number```其中,`/dev/mydevice`为所需创建的块设备节点路径;`major-number`为主设备号;`minor-number`为次设备号。
3. 通过以下命令设置所创建的块设备节点的权限:```sudo chmod permissions /dev/mydevice```其中,`permissions`为所需设置的权限。
三、创建字符设备节点在Linux系统中,字符设备是一种以字符流的形式进行读写的设备,常见的字符设备有串口设备、打印机等。
通过mknod命令可以创建字符设备节点,步骤如下:1. 以root身份登录Linux系统。
2. 打开终端,并执行以下命令:```sudo mknod /dev/mydevice c major-number minor-number```其中,`/dev/mydevice`为所需创建的字符设备节点路径;`major-number`为主设备号;`minor-number`为次设备号。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Linux 下进程之间通信可以用命名管道FIFO 完成。
命名管道是一种特殊类型的文件,因为Linux 中所有事物都是文件,它在文件系统中以文件名的形式存在。
在程序中,我们可以使用两个不同的函数调用来建立管道:#include <sys/types.h>#include <sys/stat.h> int mkfifo(const char *filename, mode_t mode);int mknode(const char *filename, mode_t mode | S_IFIFO, (dev_t) 0 );下面先来创建一个管道:view plaincopy to clipboardprint? #include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <sys/stat.h>int main(){int res = mkfifo("/tmp/my_fifo", 0777);if (res == 0){printf("FIFO created\n");}exit(EXIT_SUCCESS);}#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <sys/stat.h>int main(){int res = mkfifo("/tmp/my_fifo", 0777); if (res == 0){printf("FIFO created\n");} exit(EXIT_SUCCESS);}编译这个程序:gcc -o fifol.c fifo运行这个程序:$ ./fifo1用ls 命令查看所创建的管道$ ls -lF /tmp/my_fifoprwxr-xr-x 1 root root 0 05-08 20:10 /tmp/my_fifo|注意:Is命令的输出结果中的第一个字符为p,表示这是一个管道。
最后的|符号是由Is命令的-F 选项添加的,它也表示是这是一个管道。
虽然,我们所设置的文件创建模式为“0777”但它被用户掩码(umask)设置(022)给改变了,这与普通文件创建是一样的,所以文件的最终模式为755。
打开FIFO 一个主要的限制是,程序不能是O_RDWR 模式打开FIFO 文件进行读写操作,这样做的后果未明确定义。
这个限制是有道理的,因为我们使用FIFO 只是为了单身传递数据,所以没有必要使用O_RDWR 模式。
如果一个管道以读/写方式打开FIFO ,进程就会从这个管道读回它自己的输出。
如果确实需要在程序之间双向传递数据,最好使用一对FIFO,一个方向使用一个。
当一个Linux进程被阻塞时,它并不消耗CPU资源,这种进程的同步方式对CPU而言是非常有效率的。
有关Linux 下命名管道FIFO 的读写规则可以参见之前所写的一篇文章:Linux 命名管道FIFO 的读写规则。
、实验:使用FIFO 实现进程间通信两个独立的程序:1. 生产者程序,它在需要时创建管道,然后尽可能快地向管道中写入数据。
2. 消费者程序,它从FIFO 中读取数据并丢弃它们。
生产者程序fifo2.c :view plaincopy to clipboardprint?#include <stdio.h>#include <stdlib.h>#include <string.h>#include <fcntl.h>#include <limits.h>#include <sys/types.h>#include <sys/stat.h>#define FIFO_NAME "/tmp/Linux/my_fifo"#define BUFFER_SIZE PIPE_BUF#define TEN_MEG (1024 * 1024 * 10)int main(){int pipe_fd;int res;int open_mode = O_WRONL Y;int bytes = 0;char buffer[BUFFER_SIZE + 1];if (access(FIFO_NAME, F_OK) == -1){res = mkfifo(FIFO_NAME, 0777);if (res != 0){fprintf(stderr, "Could not create fifo %s\n", FIFO_NAME); exit(EXIT_FAILURE);}}printf("Process %d opening FIFO O_WRONL Y\n", getpid()); pipe_fd = open(FIFO_NAME, open_mode);printf("Process %d result %d\n", getpid(), pipe_fd);if (pipe_fd != -1){while (bytes < TEN_MEG){res = write(pipe_fd, buffer, BUFFER_SIZE);if (res == -1){fprintf(stderr, "Write error on pipe\n"); exit(EXIT_FAILURE);}bytes += res;}close(pipe_fd);}else{exit(EXIT_FAILURE);}printf("Process %d finish\n", getpid()); exit(EXIT_SUCCESS);}#include <stdio.h>#include <stdlib.h>#include <string.h>#include <fcntl.h>#include <limits.h>#include <sys/types.h>#include <sys/stat.h>#define FIFO_NAME "/tmp/Linux/my_fifo"#define BUFFER_SIZE PIPE_BUF#define TEN_MEG (1024 * 1024 * 10)int main(){int pipe_fd;int res;int open_mode = O_WRONL Y;int bytes = 0;char buffer[BUFFER_SIZE + 1];if (access(FIFO_NAME, F_OK) == -1){res = mkfifo(FIFO_NAME, 0777);if (res != 0){fprintf(stderr, "Could not create fifo %s\n", FIFO_NAME); exit(EXIT_FAILURE);}}printf("Process %d opening FIFO O_WRONL Y\n", getpid()); pipe_fd = open(FIFO_NAME, open_mode);printf("Process %d result %d\n", getpid(), pipe_fd);if (pipe_fd != -1){while (bytes < TEN_MEG){res = write(pipe_fd, buffer, BUFFER_SIZE);if (res == -1){fprintf(stderr, "Write error on pipe\n"); exit(EXIT_FAILURE);}bytes += res;}close(pipe_fd);}else{exit(EXIT_FAILURE);}printf("Process %d finish\n", getpid());exit(EXIT_SUCCESS);}消费者程序fifo3.c :view plaincopy to clipboardprint?#include <stdio.h>#include <stdlib.h>#include <string.h>#include <fcntl.h>#include <limits.h>#include <sys/types.h>#include <sys/stat.h>#define FIFO_NAME "/tmp/Linux/my_fifo"#define BUFFER_SIZE PIPE_BUFint main(){int pipe_fd;int res;int open_mode = O_RDONL Y; char buffer[BUFFER_SIZE + 1]; int bytes = 0;memset(buffer, '\0', sizeof(buffer));printf("Process %d opeining FIFO O_RDONL Y\n", getpid()); pipe_fd = open(FIFO_NAME, open_mode);printf("Process %d result %d\n", getpid(), pipe_fd);if (pipe_fd != -1){do{res = read(pipe_fd, buffer, BUFFER_SIZE); bytes += res;}while(res > 0);close(pipe_fd);}else{exit(EXIT_FAILURE);}printf("Process %d finished, %d bytes read\n", getpid(), bytes); exit(EXIT_SUCCESS);}#include <stdio.h>#include <stdlib.h>#include <string.h>#include <fcntl.h>#include <limits.h>#include <sys/types.h>#include <sys/stat.h>#define FIFO_NAME "/tmp/Linux/my_fifo"#define BUFFER_SIZE PIPE_BUF int main(){int pipe_fd;int res;int open_mode = O_RDONL Y; charbuffer[BUFFER_SIZE + 1];int bytes = 0;memset(buffer, '\0', sizeof(buffer));printf("Process %d opeining FIFO O_RDONL Y\n", getpid()); pipe_fd = open(FIFO_NAME, open_mode);printf("Process %d result %d\n", getpid(), pipe_fd);if (pipe_fd != -1){do{res = read(pipe_fd, buffer, BUFFER_SIZE); bytes += res;}while(res > 0);close(pipe_fd);}else{exit(EXIT_FAILURE);}printf("Process %d finished, %d bytes read\n", getpid(), bytes); exit(EXIT_SUCCESS);}编译这两个程序:gcc -o fifo2 fifo2.cgcc -o fifo3 fifo3.c运行这两个程序:[root@localhost chaper12]# ./fifo2 & a后台执行,写数据[2] 23121Process 23121 opening FIFO O_WRONL Y[root@localhost chaper12]# time ./fifo3 a读数据Process 24155 opeining FIFO O_RDONL YProcess 23121 result 3Process 24155 result 3Process 23121 finishProcess 24155 finished, 10485760 bytes read[2]- Done ./fifo2real 0m0.214suser 0m0.000ssys 0m0.179s以上两个程序均是使用阻塞模式FIFO。