帝国cms怎样做网站迁移,wwr下载建设网站,唯品会网站推广策略,信用体系网站建设一体化建设1 简介
Linux进程通信机制#xff1a;
管道信号量消息队列共享内存socket通信
2 管道 管道其实质是由内核管理的一个缓冲区 形象地认为管道的两端连接着两个进程#xff1a;
一个进程进行信息输出#xff0c;将数据写入管道#xff1b;另一个进程进行信息输入#xff…1 简介
Linux进程通信机制
管道信号量消息队列共享内存socket通信
2 管道 管道其实质是由内核管理的一个缓冲区 形象地认为管道的两端连接着两个进程
一个进程进行信息输出将数据写入管道另一个进程进行信息输入从管道中读取信息。
管道分为
匿名管道只能用于有亲缘关系的进程间通信进程退出后管道会被销毁。命名管道命名管道与进程的联系较弱相当于一个读写内存的接口进程退出后命名管道依然存在。
2.1 匿名管道
匿名管道的使用流程如下 ①在进程中创建匿名管道pipe函数 ②关闭进程中不使用的管道端口close函数 ③在待通信的进程中分别对管道的读、写端口进行操作read/write函数 ④关闭管道close函数。
2.1.1 pipe函数
#include unistd.h
int pipe(int pipefd[2]);功能创建匿名管道
参数说明
pipefd传入参数一个文件描述符数组Linux将管道抽象为一个特殊文件。
返回值说明
成功返回0.不成功返回-1。
【案例1】使用pipe()实现父子进程间通信父进程作为读端子进程作为写端。
#include stdio.h
#include stdlib.h
#include string.h
#include unistd.h
#include sys/types.h
#include sys/wait.h
int main(){int tempFd[2];//定义文件描述符数组int tempRetpipe(tempFd);//创建管道if(tempRet -1){ perror(pipe);exit(1);} pid_t tempPidfork();if(tempPid 0){//父进程—读close(tempFd[1]);//关闭写端char tempBuf[64]{0};tempRet read(tempFd[0], tempBuf, sizeof(tempBuf));//读数据close(tempFd[0]);write(STDOUT_FILENO, tempBuf, tempRet);//将读到的数据写到标准输出wait(NULL);} else if(tempPid 0){//子进程—写close(tempFd[0]);//关闭读端char *tempStrhello,pipe\n;write(tempFd[1], tempStr, strlen(tempStr)1);//写数据close(tempFd[1]);}//of ifreturn 0;
}//of main分析如下 pipe()创建管道后读端的文件描述符为fd[0]写端的文件描述符为fd[1] 调用fork后父子进程共享文件描述符文件描述符与管道的关系如图所示
父进程进行读操作子进程进行写操作使用close()函数关闭父进程的写端与子进程的读端。
2.1.2 dup2函数
【案例2】使用管道实现兄弟进程间通信兄弟进程实现命令“ls | wc –l”的功能。
在实现本案例时会用到重定向函数dup2
#include unistd.h
int dup2(int oldfd, int newfd);其功能是将参数oldfd的文件描述符复制给newfd若函数调用成功则返回newfd否则返回-1并设置errno。
#include stdio.h
#include stdlib.h
#include unistd.h
int main(){int tempFd[2];int tempRet pipe(tempFd);if(tempRet -1){perror(pipe err);exit(1);}//of if int i;pid_t tempPid, tempWpid;for(i0; i2; i){//2个子if((tempPid fork()) 0){break;}//of if}//of ifif(2 i){//父进程回收子进程close(tempFd[0]); //关闭读close(tempFd[1]); //关闭写tempWpid wait(NULL);printf(wait child 1 success,pid%d\n, tempWpid );tempPid wait(NULL);printf(wait child 2 success,pid%d\n, tempPid);} else if(0 i){//子进程1—写close(tempFd[0]);dup2(tempFd[1], STDOUT_FILENO);//定向到标准输出execlp(ls, ls, NULL);} else if(1 i){//子进程2—读close(tempFd[1]);dup2(tempFd[0], STDIN_FILENO);execlp(wc, wc, -l, NULL);}//of ifreturn 0;
}//of main注意
int execlp(const char *file, const char *arg, ...);execlp是一个可变参数函数。它需要2个const char *。其余的参数(如果有的话)为转移到运行程序的附加参数也是char * 最后一个参数必须是NULL指针。 所以文件参数是要执行的可执行文件的路径名。 arg是我们想在可执行文件中显示为argv [0]的字符串。按照惯例argv [0]只是可执行文件的文件名通常它被设置为与文件相同。
兄弟进程间通信进程文件描述符与管道的关系如图所示 实线所示的箭头为编程中需要保留的文件描述符
2.1.3 popen/pclose函数
Linux标准I/O库两个函数popen()和pclose()可完成管道通信的流程。
#include stdio.h
FILE *popen(const char *command, const char *type);
int pclose(FILE *stream);功能 popen函数的功能是
调用pipe()函数创建管道调用fork()函数创建子进程之后在子进程中通过execve()函数调用shell命令执行相应功能。
pclose函数的功能
关闭popen()打开的I/O流通过调用wait()函数等待子进程命令执行结束返回shell的终止状态防止产生僵尸进程。
参数说明 popen函数的参数
command命令;type指定命令类型输入w/输出r
pclose函数的参数
streamI/O流。
返回值说明 popen函数的返回值
成功管道文件的描述符不成功返回-1。
pclose函数的返回值
成功0不成功-1。
【案例3】使用popen与pclose函数实现管道通信。
#include stdio.h
#include stdlib.h
#include unistd.h
int main(){FILE *tempRfp,*tempWfp;char temBuf[100];tempRfp popen(ls,r); //读取命令执行结果tempWfp popen(wc -l,w); //将管道中的数据传递给进程while(fgets(temBuf, sizeof(temBuf), tempRfp)!NULL){fputs(temBuf, tempWfp);}//of while pclose(tempRfp);pclose(tempWfp);return 0;
}//of main2.2 命名管道
#include sys/type.h
#include sys/stat.hint mkfifo(const char *pathname, mode_t mode);功能创建命名管道FIFO文件命名管道与系统中的一个路径名关联以文件的形式存在于文件系统中通过FIFO的路径名访问FIFO文件实现进程间通信。
参数说明
pathname管道文件的路径名通过FIFO路径名访问FIFO文件;mode指定FIFO的权限
返回值说明
成功0不成功-1并设置errno。
【案例4】使用FIFO实现没有亲缘关系进程间的通信。没有亲缘关系的进程间通信需要两段程序来实现
fifo_write.c实现FIFO的写操作fifo_read.c实现FIFO的读操作。
fifo_write.c
#include stdio.h
#include stdlib.h
#include string.h
#include unistd.h
#include sys/types.h
#include sys/stat.h
#include fcntl.h
int main(int paraArgc,char *paraArgv[]){if(paraArgc 2){ //判断是否传入文件名printf(./a.out fifoname\n);exit(1);}//of ifint tempRet access(paraArgv[1], F_OK); //判断fifo文件是否存在if(tempRet -1){ //若fifo不存在就创建fifo int tempFIFO mkfifo(paraArgv[1], 0664);if(tempFIFO -1){ //判断文件是否创建成功perror(mkfifo);exit(1);} else{printf(fifo creat success!\n);}//of if}//of ifint tempFd open(paraArgv[1], O_WRONLY); //读写方式打开while(1){ //循环写入数据char *tempStrphello,world!;write(tempFd, tempStrp, strlen(tempStrp)1);sleep(1);}//of whileclose(tempFd);return 0;
}//of mainfifo_read.c
#include stdio.h
#include stdlib.h
#include string.h
#include unistd.h
#include sys/types.h
#include sys/stat.h
#include fcntl.h
int main(int paraArgc,char *paraArgv[]){if(paraArgc 2){ //判断是否传入文件名printf(./a.out fifoname\n);exit(1);}//of ifint tempRet access(paraArgv[1], F_OK); //判断fifo文件是否存在if(tempRet -1){ //若fifo不存在就创建fifo int tempFIFO mkfifo(paraArgv[1], 0664);if(tempFIFO -1){ //判断文件是否创建成功perror(mkfifo);exit(1);} else{printf(fifo creat success!\n);}//of if}//of ifint tempFd open(paraArgv[1], O_RDONLY); //只读方式打开if(tempFd -1){perror(open);exit(1);}//of ifwhile(1){ //不断读取fifo中的数据并打印char temBuf[1024]{0};read(tempFd, temBuf, sizeof(temBuf));printf(buf%s\n, temBuf);}//of whileclose(tempFd); //关闭文件return 0;
}//of mainFIFO文件和普通文件的区别
FIFO文件是对内存进行操作普通文件是存储在硬盘对内存的的读取会比硬盘的读写要快很多两个进程通过普通文件通信当然也是可以的。