企业网站建设情况汇报,项目网站的建设有两种模式,展台设计灵感网站,网站开发哪些TOC
目录 进程间通信的介绍
进程间通信的概念
进程间通信的目的
进程间通信的本质
进程间通信的分类
管道
什么是管道
匿名管道
pipe函数
匿名管道使用步骤
管道读写规则
管道的特点
1、管道内部自带同步与互斥机制
2、管道的生命周期随进程
3、管道提供的是流式…TOC
目录 进程间通信的介绍
进程间通信的概念
进程间通信的目的
进程间通信的本质
进程间通信的分类
管道
什么是管道
匿名管道
pipe函数
匿名管道使用步骤
管道读写规则
管道的特点
1、管道内部自带同步与互斥机制
2、管道的生命周期随进程
3、管道提供的是流式服务
4、管道是半双工通信的
管道的四种特殊情况
管道的大小
方法一使用man手册
方法二使用ulimit命令
方法三自行测试
命名管道
命名管道的原理
使用命令创建命名管道
创建一个命名管道
命名管道的打开规则
用命名管道实现serveclient通信
用命名管道实现派发计算任务
用命名管道实现文件拷贝
命令行当中的管道 进程间通信的介绍
进程间通信的概念
进程间通信简称IPCInterprocess communication进程间通信就是在不同进程之间传播或交换信息。
进程间通信的目的
数据传输 一个进程需要将它的数据发送给另一个进程。资源共享 多个进程之间共享同样的资源。通知事件 一个进程需要向另一个或一组进程发送消息通知它它们发生了某种事件比如进程终止时需要通知其父进程。进程控制 有些进程希望完全控制另一个进程的执行如Debug进程此时控制进程希望能够拦截另一个进程的所有陷入和异常并能够及时知道它的状态改变。
进程间通信的本质
进程间通信的本质就是让不同的进程看到同一份资源。
由于各个运行进程之间具有独立性这个独立性主要体现在数据层面而代码逻辑层面可以私有也可以公有例如父子进程因此各个进程之间要实现通信是非常困难的。
各个进程之间若想实现通信一定要借助第三方资源这些进程就可以通过向这个第三方资源写入或是读取数据进而实现进程之间的通信这个第三方资源实际上就是操作系统提供的一段内存区域
因此进程间通信的本质就是让不同的进程看到同一份资源内存文件内核缓冲等。 由于这份资源可以由操作系统中的不同模块提供因此出现了不同的进程间通信方式。
进程间通信的分类
管道
匿名管道命名管道
System V IPC
System V 消息队列System V 共享内存System V 信号量
POSIX IPC
消息队列共享内存信号量互斥量条件变量读写锁
管道
什么是管道
管道是Unix中最古老的进程间通信的形式我们把从一个进程连接到另一个进程的数据流称为一个1“管道”。
例如统计我们当前使用云服务器上的登录用户个数。 其中who命令和wc命令都是两个程序当它们运行起来后就变成了两个进程who进程通过标准输出将数据打到“管道”当中wc进程再通过标准输入从“管道”当中读取数据至此便完成了数据的传输进而完成数据的进一步加工处理。 注明 who命令用于查看当前云服务器的登录用户一行显示一个用户wc -l用于统计当前的行数。
匿名管道
匿名管道用于进程间通信且仅限于本地父子进程之间的通信。
进程间通信的本质就是让不同的进程看到同一份资源使用匿名管道实现父子进程间通信的原理就是让两个父子进程先看到同一份被打开的文件资源然后父子进程就可以对该文件进行写入或是读取操作进而实现父子进程间通信。
注
这里父子进程看到的同一份文件资源是由操作系统来维护的所以当父子进程对该文件进行写入操作时该文件缓冲区当中的数据并不会进行写时拷贝。管道虽然用的是文件的方案但操作系统一定不会把进程进行通信的数据刷新到磁盘当中因为这样做有IO参与会降低效率而且也没有必要。也就是说这种文件是一批不会把数据写到磁盘当中的文件换句话说磁盘文件和内存文件不一定是一一对应的有些文件只会在内存当中存在而不会在磁盘当中存在。
pipe函数
pipe函数用于创建匿名管道pip函数的函数原型如下
int pipe(int pipefd[2]);pipe函数的参数是一个输出型参数数组pipefd用于返回两个指向管道读端和写端的文件描述符
数组元素含义pipefd[0]管道读端的文件描述符pipefd[1]管道写端的文件描述符
pipe函数调用成功时返回0调用失败时返回-1。
源码如下
struct pipe_buffer {struct page *page;unsigned int offset, len;const struct pipe_buf_operations *ops;unsigned int flags;unsigned long private;
};其中我们的管道文件拥有一个缓冲区这个缓冲区有一个专门的struct pipe_buf_operations结构体用来处理它的输入输出方法以及flags用来标识当前缓冲区的装态
匿名管道使用步骤
在创建匿名管道实现父子进程间通信的过程中需要pipe函数和fork函数搭配使用具体步骤如下
1、父进程调用pipe函数创建管道。 2、父进程创建子进程。 3、父进程关闭写端子进程关闭读端。 注
管道只能够进行单向通信因此当父进程创建完子进程后需要确认父子进程谁读谁写然后关闭相应的读写端。从管道写端写入的数据会被内核缓冲直到从管道的读端被读取。
我们可以站在文件描述符的角度再来看看这三个步骤
1、父进程调用pipe函数创建管道 2、父进程创建子进程 3、父进程关闭写端子进程关闭读端 例如在以下代码当中父进程向匿名管道当中写入10行数据子进程从匿名管道当中将数据读出。
#include iostream
#include vector
#include cstdio
#include cstring
#include ctime
#include cstdlib
#include sys/wait.h
#include sys/types.h
#include unistd.h
#include Log.hpp
using namespace std;#define NUM 1024//匿名管道int main( )
{//创建管道int pipefd[2] {0};if(pipe(pipefd) ! 0){cerr pipe error endl;return 1;}//2.创建子进程pid_t id fork();if(id 0){cerr fork error endl;return 2;}else if(id 0){//3.子进程管道// 子进程来进行读取子进程就应该关掉写端close(pipefd[1]);char buffer[NUM];while(1){Log(等待写入, Debug) endl;;memset(buffer, 0, sizeof(buffer));ssize_t s read(pipefd[0], buffer, sizeof(buffer) - 1);if(s 0){//读取成功buffer[s] \0;cout 子进程收到消息 内容是: buffer endl;}else if(s 0){cout 父进程写完了子进程可以退出了 endl;break;}else {cerr err while child read pipe endl;}}close(pipefd[0]);exit(0);}else{//4.父进程管道//父进程来进行写入 就应该关掉读端close(pipefd[0]);const char* msg 我是父进程这次发出的信息编号是;int cnt 0;while(cnt 10){char sendBuffer[1024];sprintf(sendBuffer, %s : %d, msg, cnt);//格式化控制字符串write(pipefd[1], sendBuffer, strlen(sendBuffer));cnt;cout cnt: cnt endl;sleep(1);}close(pipefd[1]);cout 父进程输出完毕 endl;}//父进程等待子进程结束pid_t res waitpid(id, nullptr, 0);if(res 0){cout 等待子进程成功 endl;}cout 子进程退出 endl;return 0;
} 这里我们可以查看一下代码并没有sleep的停止语句但是为什么在输出的时候父进程输出一次子进程输出一次父进程休眠的时候子进程看起来啥事没有做。实际上子进程是在等待父进程对管道的写入。
管道读写规则
pipe2函数与pipe函数类似也是用于创建匿名管道其函数原型如下
int pipe2(int pipefd[2], int flags);
pipe2函数的第二个参数用于设置选项。
1、当没有数据可读时
O_NONBLOCK disableread调用阻塞即进程暂停执行一直等到有数据来为止。 O_NONBLOCK enableread调用返回-1errno值为EAGAIN。 2、当管道满的时候
O_NONBLOCK disablewrite调用阻塞直到有进程读走数据。 O_NONBLOCK enablewrite调用返回-1errno值为EAGAIN。 3、如果所有管道写端对应的文件描述符被关闭则read返回0。 4、如果所有管道读端对应的文件描述符被关闭则write操作会产生信号SIGPIPE进而可能导致write进程退出。 5、当要写入的数据量不大于PIPE_BUF时Linux将保证写入的原子性。 6、当要写入的数据量大于PIPE_BUF时Linux将不再保证写入的原子性。
管道的特点
1、管道内部自带同步与互斥机制
我们将一次只允许一个进程使用的资源称为临界资源。管道在同一时刻只允许一个进程对其进行写入或是读取操作因此管道也就是一种临界资源。
临界资源是需要被保护的若是我们不对管道这种临界资源进行任何保护机制那么就可能出现同一时刻有多个进程对同一管道进行操作的情况进而导致同时读写、交叉读写以及读取到的数据不一致等问题。
为了避免这些问题内核会对管道操作进行同步与互斥
同步 两个或两个以上的进程在运行过程中协同步调按预定的先后次序运行。比如A任务的运行依赖于B任务产生的数据。 互斥 一个公共资源同一时刻只能被一个进程使用多个进程不能同时使用公共资源。 实际上同步是一种更为复杂的互斥而互斥是一种特殊的同步。对于管道的场景来说互斥就是两个进程不可以同时对管道进行操作它们会相互排斥必须等一个进程操作完毕另一个才能操作而同步也是指这两个不能同时对管道进行操作但这两个进程必须要按照某种次序来对管道进行操作。
也就是说互斥具有唯一性和排它性但互斥并不限制任务的运行顺序而同步的任务之间则有明确的顺序关系。
2、管道的生命周期随进程
管道本质上是通过文件进行通信的也就是说管道依赖于文件系统那么当所有打开该文件的进程都退出后该文件也就会被释放掉所以说管道的生命周期随进程。
3、管道提供的是流式服务
对于进程A写入管道当中的数据进程B每次从管道读取的数据的多少是任意的这种被称为流式服务与之相对应的是数据报服务
流式服务 数据没有明确的分割不分一定的报文段。数据报服务 数据有明确的分割拿数据按报文段拿。
4、管道是半双工通信的
在数据通信中数据在线路上的传送方式可以分为以下三种
单工通信(Simplex Communication)单工模式的数据传输是单向的。通信双方中一方固定为发送端另一方固定为接收端。 半双工通信(Half Duplex)半双工数据传输指数据可以在一个信号载体的两个方向上传输但是不能同时传输。 全双工通信(Full Duplex)全双工通信允许数据在两个方向上同时传输它的能力相当于两个单工通信方式的结合。全双工可以同时(瞬时)进行信号的双向传输。 管道是半双工的数据只能向一个方向流动需要双方通信时需要建立起两个管道。
管道的四种特殊情况
在使用管道时可能出现以下四种特殊情况 写端进程不写读端进程一直读那么此时会因为管道里面没有数据可读对应的读端进程会被挂起直到管道里面有数据后读端进程才会被唤醒。 读端进程不读写端进程一直写那么当管道被写满后对应的写端进程会被挂起直到管道当中的数据被读端进程读取后写端进程才会被唤醒。 写端进程将数据写完后将写端关闭那么读端进程将管道当中的数据读完后就会继续执行该进程之后的代码逻辑而不会被挂起。 读端进程将读端关闭而写端进程还在一直向管道写入数据那么操作系统会将写端进程杀掉。 其中前面两种情况就能够很好的说明管道是自带同步与互斥机制的读端进程和写端进程是有一个步调协调的过程的不会说当管道没有数据了读端还在读取而当管道已经满了写端还在写入。读端进程读取数据的条件是管道里面有数据写端进程写入数据的条件是管道当中还有空间若是条件不满足则相应的进程就会被挂起直到条件满足后才会被再次唤醒。 第三种情况也很好理解读端进程已经将管道当中的所有数据都读取出来了而且此后也不会有写端再进行写入了那么此时读端进程也就可以执行该进程的其他逻辑了而不会被挂起。 第四种情况也不难理解既然管道当中的数据已经没有进程会读取了那么写端进程的写入将没有意义因此操作系统直接将写端进程杀掉。而此时子进程代码都还没跑完就被终止了属于异常退出那么子进程必然收到了某种信号。 我们可以通过以下代码看看情况四中子进程退出时究竟是收到了什么信号。
#include iostream
#include string.h
#include stdlib.h
#include sys/types.h
#include sys/wait.h
#include unistd.hint main(){int fd[2] {0};if(pipe(fd) 0){perror(pipe);return 1;}pid_t id fork();//创建进程if(id 0){//childclose(fd[0]); // 子进程关闭读段//子进程向管道写入数据const char* msg 我是子进程;int count 10;while(count--){write(fd[1], msg, strlen(msg));sleep (1);}close(fd[1]);exit(0);}//fatherclose(fd[1]);//父进程关闭写端close(fd[0]);//父进程直接关闭读端导致子进程直接被操作系统杀掉int status 0;waitpid(id, status, 0);printf(子进程获得的信号%d\n,status 0x7F);return 0;} 通过kill -l命令可以查看13对应的具体信号。 由此可知当发生情况四时操作系统向子进程发送的是SIGPIPE信号将子进程终止的。
管道的大小
管道的容量是有限的如果管道已满那么写端将阻塞或失败那么管道的最大容量是多少呢
方法一使用man手册
根据man手册在2.6.11之前的Linux版本中管道的最大容量与系统页面大小相同从Linux 2.6.11往后管道的最大容量是65536字节。 然后我们可以使用uname -r命令查看自己使用的Linux版本。 根据man手册我使用的是Linux 2.6.11之后的版本因此管道的最大容量是65536字节。
方法二使用ulimit命令
其次我们还可以使用ulimit -a命令查看当前资源限制的设定。 根据显示管道的最大容量是 512 × 8 4096 512\times84096512×84096 字节。
方法三自行测试
这里发现根据man手册得到的管道容量与使用ulimit命令得到的管道容量不同那么此时我们可以自行进行测试。
前面说到若是读端进程一直不读取管道当中的数据写端进程一直向管道写入数据当管道被写满后写端进程就会被挂起。据此我们可以写出以下代码来测试管道的最大容量。
#include unistd.h
#include stdio.h
#include stdlib.h
#include sys/wait.h
int main()
{int fd[2] { 0 };if (pipe(fd) 0){ //使用pipe创建匿名管道perror(pipe);return 1;}pid_t id fork(); //使用fork创建子进程if (id 0){//child close(fd[0]); //子进程关闭读端char c a;int count 0;//子进程一直进行写入一次写入一个字节while (1){write(fd[1], c, 1);count;printf(%d\n, count); //打印当前写入的字节数}close(fd[1]);exit(0);}//fatherclose(fd[1]); //父进程关闭写端//父进程不进行读取waitpid(id, NULL, 0);close(fd[0]);return 0;
}可以看到在读端进程不进行读取的情况下写端进程最多写65536字节的数据就被操作系统挂起了也就是说我当前Linux版本中管道的最大容量是65536字节。 命名管道
命名管道的原理 匿名管道只能用于具有共同祖先的进程具有亲缘关系的进程之间的通信通常一个管道由一个进程创建然后该进程调用fork此后父子进程之间就可应用该管道。 如果要实现两个毫不相关进程之间的通信可以使用命名管道来做到。命名管道就是一种特殊类型的文件两个进程通过命名管道的文件名打开同一个管道文件此时这两个进程也就看到了同一份资源进而就可以进行通信了。
注
普通文件是很难做到通信的即便做到通信也无法解决一些安全问题。命名管道和匿名管道一样都是内存文件只不过命名管道在磁盘有一个简单的映像但这个映像的大小永远为0因为命名管道和匿名管道都不会将通信数据刷新到磁盘当中。
使用命令创建命名管道
我们可以使用mkfifo命令创建一个命名管道。 可以看到创建出来的文件的类型是p代表该文件是命名管道文件。 使用这个命名管道文件就能实现两个进程之间的通信了。我们在一个进程进程A中用shell脚本每秒向命名管道写入一个字符串在另一个进程进程B当中用cat命令从命名管道当中进行读取。 现象就是当进程A启动后进程B会每秒从命名管道中读取一个字符串打印到显示器上。这就证明了这两个毫不相关的进程可以通过命名管道进行数据传输即通信。 创建一个命名管道
在程序中创建命名管道使用mkfifo函数mkfifo函数的函数原型如下
int mkfifo(const char *pathname, mode_t mode);
mkfifo函数的第一个参数是pathname表示要创建的命名管道文件。
若pathname以路径的方式给出则将命名管道文件创建在pathname路径下。若pathname以文件名的方式给出则将命名管道文件默认创建在当前路径下。注意当前路径的含义
mkfifo函数的第二个参数是mode表示创建命名管道文件的默认权限。
例如将mode设置为0666则命名管道文件创建出来的权限如下 但实际上创建出来文件的权限值还会受到umask文件默认掩码的影响实际创建出来文件的权限为mode(~umask)。umask的默认值一般为0002当我们设置mode值为0666时实际创建出来文件的权限为0664。 若想创建出来命名管道文件的权限值不受umask的影响则需要在创建文件前使用umask函数将文件默认掩码设置为0。
umask(0); //将文件默认掩码设置为0 mkfifo函数的返回值。
命名管道创建成功返回0。命名管道创建失败返回-1。
创建命名管道示例
使用以下代码即可在当前路径下创建出一个名为myfifo的命名管道。
#include stdio.h
#include sys/types.h
#include sys/stat.h#define FILE_NAME myfifoint main()
{umask(0); //将文件默认掩码设置为0if (mkfifo(FILE_NAME, 0666) 0){ //使用mkfifo创建命名管道文件perror(mkfifo);return 1;}//create success...return 0;
}运行代码后命名管道myfifo就在当前路径下被创建了。
命名管道的打开规则
1、如果当前打开操作是为读而打开FIFO时。
O_NONBLOCK disable阻塞直到有相应进程为写而打开该FIFO。O_NONBLOCK enable立刻返回成功。
2、如果当前打开操作是为写而打开FIFO时。
O_NONBLOCK disable阻塞直到有相应进程为读而打开该FIFO。O_NONBLOCK enable立刻返回失败错误码为ENXIO。
用命名管道实现serveclient通信
实现服务端(server)和客户端(client)之间的通信之前我们需要先让服务端运行起来我们需要让服务端运行后创建一个命名管道文件然后再以读的方式打开该命名管道文件之后服务端就可以从该命名管道当中读取客户端发来的通信信息了。 服务端代码如下
#include comm.hppint main()
{umask(0);//1.创建管道文件if(mkfifo(ipcPath.c_str(), MODE) 0){perror(mkfifo);exit(1);}Log(创建管道文件成功, Debug) step 1 endl;//2.正常的文件操作int fd open(ipcPath.c_str(), O_RDONLY);if(fd 0 ){perror(open);exit(2);}Log(打开管道文件成功, Debug) step 2 endl;//3.编写正常的通信代码char buffer[SIZE];while(true){memset (buffer, \0, sizeof(buffer));ssize_t s read (fd, buffer,sizeof(buffer) - 1);if(s 0){cout [ getpid() ] client say buffer endl;}else if(s 0){//end of filecerr [ getpid() ] read end of file, clien quit, server quit too! endl; break;}else{//read errorperror(read);break;}}//4.关闭文件close(fd);Log(关闭管道文件成功, Debug) step 3 endl;unlink(ipcPath.c_str());//通信完毕Log(删除管道文件成功, Debug) step 4 endl;return 0;
}
而对于客户端来说因为服务端运行起来后命名管道文件就已经被创建了所以客户端只需以写的方式打开该命名管道文件之后客户端就可以将通信信息写入到命名管道文件当中进而实现和服务端的通信。
客户端的代码如下
#include comm.hppint main()
{//1.获取管道文件int fd open(ipcPath.c_str(), O_WRONLY);if(fd 0){perror(open);exit(1);}//2.ipc过程string buffer;while(true){cout Please Enter Message Line :;std::getline(std::cin, buffer);write(fd, buffer.c_str(), buffer.size()); }//3. 关闭close(fd);return 0;
}
公用头文件
#include cstdio
#include cstdlib
#include sys/stat.h
#include fcntl.h
#include Log.hppusing namespace std;#define MODE 0664
#define SIZE 128
string ipcPath ./fifo.ipc;#endif
日志步骤记录
#ifndef _LOG_H_
#define _LOG_H_#include iostream
#include ctime
#include string
using namespace std;#define Notice 0
#define Warning 1
#define Error 2
#define Debug 3const std::string msg[] { Notice, Warning, Error, Debug};std::ostream Log(std::string message, int level)
{std::cout | (unsigned)time(nullptr) | msg[level] | message;return std::cout;
}#endif代码编写完毕后先将服务端进程运行起来之后我们就能在客户端看到这个已经被创建的命名管道文件。 接着再将客户端也运行起来此时我们从客户端写入的信息被客户端写入到命名管道当中服务端再从命名管道当中将信息读取出来打印在服务端的显示器上该现象说明服务端是能够通过命名管道获取到客户端发来的信息的换句话说此时这两个进程之间是能够通信的。 服务端和客户端之间的退出关系
当客户端退出后服务端将管道当中的数据读完后就再也读不到数据了那么此时服务端也就会去执行它的其他代码了在当前代码中是直接退出了。 当服务端退出后客户端写入管道的数据就不会被读取了也就没有意义了那么当客户端下一次再向管道写入数据时就会收到操作系统发来的13号信号(SIGPIPE)此时客户端就被操作系统强制杀掉了。 通信是在内存当中进行的
若是我们只让客户端向管道写入数据而服务端不从管道读取数据那么这个管道文件的大小会不会发生变化呢
#include comm.hpp//server.c
int main()
{umask(0); //将文件默认掩码设置为0if (mkfifo(ipcPath.c_str(), 0666) 0){ //使用mkfifo创建命名管道文件perror(mkfifo);return 1;}int fd open(ipcPath.c_str(), O_RDONLY); //以读的方式打开命名管道文件if (fd 0){perror(open);return 2;}while (1){//服务端不读取管道信息}close(fd); //通信完毕关闭命名管道文件return 0;
}可以看到尽管服务端不读取管道当中的数据但是管道当中的数据并没有被刷新到磁盘使用ll命令看到命名管道文件的大小依旧为0也就说明了双方进程之间的通信依旧是在内存当中进行的和匿名管道通信是一样的。 用命名管道实现派发计算任务
需要注意的是两个进程之间的通信并不是简单的发送字符串而已服务端是会对客户端发送过来的信息进行某些处理的。
这里我们以客户端向服务端派发计算任务为例客户端通过管道向服务端发送双操作数的计算请求服务端接收到客户端的信息后需要计算出相应的结果。
这里我们无需更改客户端的代码只需改变服务端处理通信信息的逻辑即可。 用命名管道实现文件拷贝
这里我们再用命名管道实现一下文件的拷贝
需要拷贝的文件是file.txt该文件当中的内容如下 我们要做的就是让客户端将file.txt文件通过管道发送给服务端在服务端创建一个file-bat.txt文件并将从管道获取到的数据写入file-bat.txt文件当中至此便实现了file.txt文件的拷贝。
其中服务端需要做的就是创建命名管道并以读的方式打开该命名管道再创建一个名为file-bat.txt的文件之后需要做的就是将从管道当中读取到的数据写入到file-bat.txt文件当中即可。
服务端的代码如下
#include comm.hpp//server.cint main()
{umask(0); //将文件默认掩码设置为0if (mkfifo(ipcPath.c_str(), 0666) 0){ //使用mkfifo创建命名管道文件perror(mkfifo);return 1;}int fd open(ipcPath.c_str(), O_RDONLY); //以读的方式打开命名管道文件if (fd 0){perror(open);return 2;}//创建文件file-bat.txt并以写的方式打开该文件int fdout open(file-bat.txt, O_CREAT | O_WRONLY, 0666);if (fdout 0){perror(open);return 3;}char msg[128];while (1){msg[0] \0; //每次读之前将msg清空//从命名管道当中读取信息ssize_t s read(fd, msg, sizeof(msg)-1);if (s 0){write(fdout, msg, s); //将读取到的信息写入到file-bat.txt文件当中}else if (s 0){cout client quit! endl;break;}else{cout read error! endl;break;}}close(fd); //通信完毕关闭命名管道文件close(fdout); //数据写入完毕关闭file-bat.txt文件return 0;
}
而客户端需要做的就是以写的方式打开这个已经存在的命名管道文件再以读的方式打开file.txt文件之后需要做的就是将file.txt文件当中的数据读取出来并写入管道当中即可。
客户端的代码如下
#include comm.hppint main()
{int fd open(ipcPath.c_str(), O_WRONLY);//以写的方法打开命令管道文件if(fd 0){perror(open);return 1;}int fdin open(file.txt, O_RDONLY);if(fdin 0){perror(open);return 2;}char msg[128];while(1){//从file.txt文档中读取数据ssize_t s read(fdin, msg, sizeof (msg));if(s 0){write(fd, msg, s);//将读取到的数据写入到命名管道中}else if(s 0){cout read end of file! endl;break;}else{cout read error endl;break;}}close( fd);close(fdin);return 0;}
编写完代码后先运行服务端再运行客户端一瞬间这两个进程就相继运行结束了。 查看这个目录就会发现一个file.txt文件的拷贝。 内容和file.txt一样 使用管道实现文件的拷贝有什么意义
因为这里是使用管道在本地进行的文件拷贝所以看似没什么意义但我们若是将这里的管道想象成“网络”将客户端想象成“Windows Xshell”再将服务端想象成“centos服务器”。那我们此时实现的就是文件上传的功能若是将方向反过来那么实现的就是文件下载的功能。
命名管道和匿名管道的区别
匿名管道由pipe函数创建并打开。命名管道由mkfifo函数创建由open函数打开。FIFO命名管道与pipe匿名管道之间唯一的区别在于它们创建与打开的方式不同一旦这些工作完成之后它们具有相同的语义。
命令行当中的管道
现有file.txt文件文件当中的内容如下 我们可以利用管道“|”同时使用cat命令和grep命令进而实现文本过滤。 这里的 | 就是命令行当中的管道
由于匿名管道只能用于有亲缘关系的进程之间的通信而命名管道可以用于两个毫不相关的进程之间的通信因此我们可以先看看命令行当中用管道“|”连接起来的各个进程之间是否具有亲缘关系。
下面通过管道“|”连接了三个进程通过ps命令查看这三个进程可以发现这三个进程的PPID是相同的也就是说它们是由同一个父进程创建的子进程。 而它们的父进程实际上就是命令行解释器这里为bash。
也就是说由管道“|”连接起来的各个进程是有亲缘关系的它们之间互为兄弟进程。
现在我们已经知道了若是两个进程之间采用的是命名管道那么在磁盘上必须有一个对应的命名管道文件名而实际上我们在使用命令的时候并不存在类似的命名管道文件名因此命令行上的管道实际上是匿名管道。 文章转载自: http://www.morning.mkbc.cn.gov.cn.mkbc.cn http://www.morning.ljwyc.cn.gov.cn.ljwyc.cn http://www.morning.qnzld.cn.gov.cn.qnzld.cn http://www.morning.qgjxt.cn.gov.cn.qgjxt.cn http://www.morning.zdgp.cn.gov.cn.zdgp.cn http://www.morning.ai-wang.cn.gov.cn.ai-wang.cn http://www.morning.qcfgd.cn.gov.cn.qcfgd.cn http://www.morning.lcmhq.cn.gov.cn.lcmhq.cn http://www.morning.rchsr.cn.gov.cn.rchsr.cn http://www.morning.rbsxf.cn.gov.cn.rbsxf.cn http://www.morning.swkzr.cn.gov.cn.swkzr.cn http://www.morning.cqwb25.cn.gov.cn.cqwb25.cn http://www.morning.cgthq.cn.gov.cn.cgthq.cn http://www.morning.lgrkr.cn.gov.cn.lgrkr.cn http://www.morning.rqjfm.cn.gov.cn.rqjfm.cn http://www.morning.qbjrl.cn.gov.cn.qbjrl.cn http://www.morning.xmxbm.cn.gov.cn.xmxbm.cn http://www.morning.slfmp.cn.gov.cn.slfmp.cn http://www.morning.ghpld.cn.gov.cn.ghpld.cn http://www.morning.dnmgr.cn.gov.cn.dnmgr.cn http://www.morning.bmncq.cn.gov.cn.bmncq.cn http://www.morning.rbnnq.cn.gov.cn.rbnnq.cn http://www.morning.thwcg.cn.gov.cn.thwcg.cn http://www.morning.lbqt.cn.gov.cn.lbqt.cn http://www.morning.nktgj.cn.gov.cn.nktgj.cn http://www.morning.xsgxp.cn.gov.cn.xsgxp.cn http://www.morning.kehejia.com.gov.cn.kehejia.com http://www.morning.sypby.cn.gov.cn.sypby.cn http://www.morning.jhxtm.cn.gov.cn.jhxtm.cn http://www.morning.bfcrp.cn.gov.cn.bfcrp.cn http://www.morning.kryn.cn.gov.cn.kryn.cn http://www.morning.ffbp.cn.gov.cn.ffbp.cn http://www.morning.prhqn.cn.gov.cn.prhqn.cn http://www.morning.jcxyq.cn.gov.cn.jcxyq.cn http://www.morning.prgdy.cn.gov.cn.prgdy.cn http://www.morning.pxwjp.cn.gov.cn.pxwjp.cn http://www.morning.zqdhr.cn.gov.cn.zqdhr.cn http://www.morning.hwlmy.cn.gov.cn.hwlmy.cn http://www.morning.zpqbh.cn.gov.cn.zpqbh.cn http://www.morning.gtqx.cn.gov.cn.gtqx.cn http://www.morning.bnlch.cn.gov.cn.bnlch.cn http://www.morning.yxmcx.cn.gov.cn.yxmcx.cn http://www.morning.jwtjf.cn.gov.cn.jwtjf.cn http://www.morning.inheatherskitchen.com.gov.cn.inheatherskitchen.com http://www.morning.fdrwk.cn.gov.cn.fdrwk.cn http://www.morning.nndbz.cn.gov.cn.nndbz.cn http://www.morning.qgtfl.cn.gov.cn.qgtfl.cn http://www.morning.llmhq.cn.gov.cn.llmhq.cn http://www.morning.nqypf.cn.gov.cn.nqypf.cn http://www.morning.hwzzq.cn.gov.cn.hwzzq.cn http://www.morning.weiwt.com.gov.cn.weiwt.com http://www.morning.bpmnl.cn.gov.cn.bpmnl.cn http://www.morning.jmbgl.cn.gov.cn.jmbgl.cn http://www.morning.kwwkm.cn.gov.cn.kwwkm.cn http://www.morning.cjsnj.cn.gov.cn.cjsnj.cn http://www.morning.cykqb.cn.gov.cn.cykqb.cn http://www.morning.dwwbt.cn.gov.cn.dwwbt.cn http://www.morning.dtnjr.cn.gov.cn.dtnjr.cn http://www.morning.dfojgo.cn.gov.cn.dfojgo.cn http://www.morning.pmdzd.cn.gov.cn.pmdzd.cn http://www.morning.rqqlp.cn.gov.cn.rqqlp.cn http://www.morning.rqxtb.cn.gov.cn.rqxtb.cn http://www.morning.krdmn.cn.gov.cn.krdmn.cn http://www.morning.xpqyf.cn.gov.cn.xpqyf.cn http://www.morning.gyxwh.cn.gov.cn.gyxwh.cn http://www.morning.dydqh.cn.gov.cn.dydqh.cn http://www.morning.rfdqr.cn.gov.cn.rfdqr.cn http://www.morning.kmjbs.cn.gov.cn.kmjbs.cn http://www.morning.fdfdz.cn.gov.cn.fdfdz.cn http://www.morning.njntp.cn.gov.cn.njntp.cn http://www.morning.nytqy.cn.gov.cn.nytqy.cn http://www.morning.yqqxj26.cn.gov.cn.yqqxj26.cn http://www.morning.gbpanel.com.gov.cn.gbpanel.com http://www.morning.wjjsg.cn.gov.cn.wjjsg.cn http://www.morning.youngbase.cn.gov.cn.youngbase.cn http://www.morning.lhhkp.cn.gov.cn.lhhkp.cn http://www.morning.rwqk.cn.gov.cn.rwqk.cn http://www.morning.rkrcd.cn.gov.cn.rkrcd.cn http://www.morning.nqyzg.cn.gov.cn.nqyzg.cn http://www.morning.krgjc.cn.gov.cn.krgjc.cn