Linux的进程间的通信
来源:互联网 发布:淘宝卖cf神器是真的吗 编辑:程序博客网 时间:2024/04/27 20:51
#define STDIN_FILENO 0#define STDOUT_FILENO 1#define STDERR_FILENO 2
一,管道进程的pipe函数和dup2函数组合使用父子进程间通信
参数是数组管道文件描述符
pipe参数是:
- fd[0]是读文件描述符,
- fd[2]是写文件描述符
int pipe(int pipefd[2]);
案例1:
/************************************************************************* > File Name: pipe.c > Author: songli > QQ: 2734030745 > Mail: 15850774503@163.com > CSDN: http://my.csdn.net/Poisx > github: https://github.com/chensongpoixs > Created Time: Fri 20 Oct 2017 10:22:29 PM CST ************************************************************************/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/stat.h>#include <sys/types.h>#include <sys/wait.h>#include <unistd.h>#include <fcntl.h>int main(int argc, char *argv[]){ //管道数组文件描述符 int fd[2]; int ret; int i, n = 2; //创建管道 ret = pipe(fd); //文件描述符 pid_t pid; if (ret < 0) { perror("pipe error"); return -1; } for (i = 0; i < n; i++) { //创建子进程 pid = fork(); if (pid < 0) // 异常处理 { perror("fork error"); return -1; } else if (pid > 0) // 父进程的操作 { printf("father fpid:%d, cpid:%d\n", getpid(), pid); } else if (pid == 0) //子进程的操作 { printf("child fpid:%d, cpid:%d\n", getppid(), getpid()); break; //防止子线程创建子进程 } } //=============== 子进程的操作============================= if (i == 0) { printf("no child n = %d, cpid:%d\n", i, getpid()); //=================写入数据 ===================== close(fd[0]); //关闭读取文件描述符 //标准输入也是 文件描述符 中的1 dup2(fd[1], STDOUT_FILENO); // 执行 写入命令 execlp("ps", "ps", "-ef", NULL); close(fd[1]); //关闭写入文件描述符 return 0; //signal 正常退出 } if (i == 1) { printf("no child n = %d, cpid:%d\n", i, getpid()); //=================写入数据 ===================== close(fd[1]); //关闭 写描述符文件描述符 //标准输出也是 文件描述符 中的1 dup2(fd[0], STDIN_FILENO); // 执行 写入命令 execlp("grep", "grep", "--color", "bash", NULL); close(fd[0]); //关闭写入文件描述符 return 0; //signal 正常退出 } //================= 主进程的操作 ======================== if (i == n) { //pcb 进程块pid pid_t wpid; int status; while (1) { //等待线程 wpid = waitpid(-1, &status, WNOHANG ); if (wpid == 0) //有子进程程的操作 { sleep(1); continue; } else if (wpid == -1) // 没有子进程的操作 { printf("退出子进程的wpid:%d\n", wpid); exit(0); } else if (wpid > 0) //什么原因退出 { if (WIFEXITED(status)) //正常退出 { printf("子进程wpid:%d, status:%d\n", wpid, WEXITSTATUS(status)); } if (WIFSIGNALED(status)) { printf("子进程wpid:%d, status:%d\n", wpid, WTERMSIG(status)); } } } } return 0;}
效果图
和fcntl函数一起使用可以数组read函数非阻塞
/************************************************************************* > File Name: pipe_fcntl.c > Author: songli > QQ: 2734030745 > Mail: 15850774503@163.com > CSDN: http://my.csdn.net/Poisx > github: https://github.com/chensongpoixs > Created Time: Fri 20 Oct 2017 10:47:08 PM CST ************************************************************************/#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>#include <fcntl.h>#include <string.h>int main(int argc, char *argv[]){ //数组文件描述符 int fd[2]; int ret; char buf[1024]; //创建管道 ret = pipe(fd); if (ret < 0) { perror("pipe error"); return -1; } //pcb进程控制块pid pid_t pid; //创建子线程 pid = fork(); if (pid < 0) //异常处理 { perror("fork error"); return -1; } else if (pid > 0) //父进程的处理 { printf("father fpid:%d, cpid:%d\n", getpid(), pid); //==============读取数据================== close(fd[1]); //关闭写文件操作 //================== 在同一个进程中使用非阻塞使用fcntl函数 ========================================= int flags = fcntl(fd[0], F_GETFL ); flags |= O_NONBLOCK; fcntl(fd[0], F_SETFL, flags); //============================================================= while(1) { sleep(1); memset(buf, 0x00, sizeof(buf)); ret = read(fd[0], buf, sizeof(buf)); printf("读取数据的大小:%d buf = %s\n", ret, buf); } close(fd[0]); } else if (pid == 0) //子进程的操作 { printf("child fpid:%d, cpid:%d\n", getppid(), getpid()); //========== 写操作=================== close(fd[0]); //关闭读取文件描述符 int i = 0; while (1) { sleep(1); memset(buf, 0x00, sizeof(buf)); sprintf(buf, "[%d]:[%s]", i++, "陈丽, 杨艳"); write(fd[1], buf, strlen(buf)); } close(fd[1]); } return 0;}
* 效果图*
二,管道 mkfifio函数的使用
mkfifo命令生成管道文件
mkfifo函数 第一参数路径, 第二是权限
int mkfifo(const char *pathname, mode_t mode);
写入数据
/************************************************************************* > File Name: fifo_write.c > Author: songli > QQ: 2734030745 > Mail: 15850774503@163.com > CSDN: http://my.csdn.net/Poisx > github: https://github.com/chensongpoixs > Created Time: Fri 20 Oct 2017 11:22:50 PM CST ************************************************************************/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/wait.h>int main(int argc, char *argv[]){ // 文件描述符 int fd; int ret; //判断是否创建管道文件 if ((ret = access("./myfifo", F_OK)) == -1) { //创建管道 ret = mkfifo("./myfifo", 0777); if (ret < 0) { perror("mkfifo error"); return -1; } } //打开文件 fd = open("./myfifo", O_RDWR); if (fd < 0) { perror("open error"); return -1; } //=====================写数据到管道中============================ while (1) { sleep(1); write(fd, "陈丽, 杨艳", strlen("杨艳")); } close(fd); return 0;}
读取数据
/*************************************************************************> File Name: fifo_read.c> Author: songli> QQ: 2734030745> Mail: 15850774503@163.com> CSDN: http://my.csdn.net/Poisx> github: https://github.com/chensongpoixs> Created Time: Fri 20 Oct 2017 11:31:07 PM CST************************************************************************/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/types.h>int main(int argc, char *argv[]){ //文件描述符 int fd; int ret; char buf[1024]; //检测是否有管道文件 if ((ret = access("./myfifo", F_OK)) == -1) { ret = mkfifo("./myfifo", 0777); if (ret < 0) { perror("mkfifo error"); return -1; } } //打开管道文件 fd = open("./myfifo", O_RDWR); if (fd < 0) { perror("open error"); return -1; } //==============读取管道中数据========================= while (1) { //================= 设置read函数非阻塞 ==================/* int flags = fcntl(fd, F_GETFL); flags |= O_NONBLOCK; fcntl(fd, F_SETFL, flags);*/ sleep(1); memset(buf, 0x00, sizeof(buf)); ret = read(fd, buf, sizeof(buf)); printf("读取数据:%d, buf = %s\n", ret, buf); } //关闭文件 close(fd); return 0;}
效果图
三,mmap内存映射的机制
每个应用程序有虚的4个G的内存 由MMU把实际 要用的映射到内存中就是内核
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/stat.h>#include <sys/types.h>#include <fcntl.h>#include <sys/mman.h>int main(int argc, char *argv[]){ //文件描述符 int fd; int len; fd = open("./text.log", O_RDWR); if (fd < 0) { perror("open error"); return -1; } //文件大小 len = lseek(fd, 0, SEEK_END); //参数一:NULL //参数二:文件的大小,不能为0 //参数三:权限 //参数四:是否同步的硬盘中 //参数五:文件指针 //参数六:文件开始位置 void *ptr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (ptr == MAP_FAILED) { perror("mmap error"); return -1; } char *p = (char*)ptr; strcpy(p, "陈丽"); //参数一:文件指针 //参数二:文件大小 munmap(ptr, len); //关闭文件 close(fd); return 0;}
没有告关系的进程之间通信
写数据的
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/mman.h>#include <sys/types.h>#include <sys/types.h>#include <unistd.h>#include <fcntl.h>int main(int argc, char *argv[]){ //文件描述符 int fd; int len; //文件大小 int ret; //状态码 //打开文件 fd = open("./text.log", O_RDWR); if (fd < 0) { perror("open error"); return -1; } //文件大小 len = lseek(fd, 0, SEEK_END); //映射到内核中 void * ptr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (ptr == MAP_FAILED) { perror("mmap error"); return -1; } char * p = (char *) ptr; strcpy(p, "陈丽, 王蓉"); //关闭 munmap(ptr, len); close(fd); return 0;}
读取数据
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/stat.h>#include <sys/types.h>#include <unistd.h>#include <sys/mman.h>#include <fcntl.h>/**读取数据mmap_read**/int main(int argc, char *argv[]){ //文件指针 int fd; int len; //文件大小 void * ptr; //映射内存地址 char buf[1024]; //打开文件 fd = open("./text.log", O_RDWR); if (fd < 0) { perror("open error"); return -1; } //文件大小 len = lseek(fd, 0, SEEK_END); //创建映射 ptr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (ptr == MAP_FAILED) { perror("mmap error"); return -1; } //=============读取 map内存的数据=================== //while (1) //{ //memset(buf, 0x00, sizeof(buf)); // read(fd, buf, sizeof(buf)); char *p = (char *) ptr; printf("读取数据:%s\n", p); //} munmap(ptr, len); //关闭文件操作 close(fd); return 0;}
进程间通信的自定义
/* *父子进程交替数数。 */#include <signal.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/types.h>#include <sys/wait.h>#include <signal.h>#include <error.h>pid_t pid;void sig_handler_p(int sig) //parent 父进程{ static int i = 1; printf("pid = %d, I'm father\t%d\n", getpid(), i); sleep(1); i += 2; kill(pid, SIGUSR1); //为避免竞态条件出现,应该在捕捉函数内完成数数及信号发送.}void sig_handler_c(int sig) //child 子进程{ static int i = 2; printf("pid = %d, I am child\t%d\n", getpid(), i); sleep(1); i += 2; kill(getppid(), SIGUSR2);}int main(void){ struct sigaction newact_p, oldact_p; //父进程使用 struct sigaction newact_c, oldact_c; //子进程使用 //子进程响应SIGUSR1 newact_c.sa_handler = sig_handler_c; sigemptyset(&newact_c.sa_mask); newact_c.sa_flags = 0; sigaction(SIGUSR1, &newact_c, &oldact_c);//注册捕捉信号(捕捉的信号,传入参数新的处理方法,传出参数旧的处理方法) //父进程响应SIGUSR2 newact_p.sa_handler = sig_handler_p; sigemptyset(&newact_p.sa_mask); newact_p.sa_flags = 0; newact_p.sa_flags |= SA_RESTART;//多加这一行可以将被信号打断的系统调用重启。 sigaction(SIGUSR2, &newact_p, &oldact_p);//注册捕捉信号(捕捉的信号,传入参数新的处理方法,传出参数旧的处理方法) pid = fork();//此时父子进程都注册了2个信号处理函数,但都只会收到其中一个信号,子进程只收SIGUSR1,父进程只收SIGUSR2 if (pid == 0) { //子进程 while (1); } else { //父进程 raise(SIGUSR2);//自己给自己发信号2 if (wait(NULL)) { //wait有可能被信号打断。 perror("wait error"); } //while (1); //或者不使用wait使用这条语句也可以实现。 } return 0;}
阅读全文
0 0
- linux进程间的通信
- Linux进程间的通信
- Linux进程间的通信
- Linux进程间的通信
- Linux进程间的通信
- Linux进程间的通信
- linux进程间的通信
- Linux进程间的通信--管道通信
- 【Linux】Linux进程间通信的方法
- Linux的进程间的通信
- Linux环境进程间的通信
- Linux下的进程间通信
- Linux下的进程间通信-详解
- Linux 下的进程间通信
- Linux进程间通信的方法
- linux系统的进程间通信方式
- Linux下的进程间通信-详解
- Linux下的进程间通信-详解 .
- excel的读取 java
- 枚举题目
- Sicily Course 213 基于单向链表的list
- 汉字的Unicode表位置
- 【基础算法】(04) 十二种排序算法(第四篇)
- Linux的进程间的通信
- 20个必会的JavaScript面试题
- 人生若只如初见
- 进程间通信——无名管道&信号量
- C语言实现对顺序表的增删改查
- warning: LF will be replaced by CRLF的解决方法
- thinking-in-java(11) 持有对象
- 用proteus实现上升沿D触发器做寄存器
- unix环境高级编程第七章阅读小结