ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Linux系统编程——进程间通信

Linux系统编程——进程间通信 进程间通信1.同一主机传统的进程间通信方式1.无名管道2.有名管道3.信号SystemV通信方式4.共享内存 --- 效率最高的通信方式5.消息队列6.信号量 --- 和线程中的信号量都是信号量机制2.不同主机 --- socket --- 网络7.socket本地socket --- 本地套接字不同主机 --- 网络套接字进程通信的原理进程空间相互独立每个进程拥有独立的4G内存空间32位但是内核空间共享所有进程间通信方式本质都是借助操作系统内核来完成的1.无名管道进程间通信 --- 在内核建立一个管道无名管道本质是一种特殊的文件不存在于硬盘中而是在内存中内核空间无名表示在文件系统中没有对应的名字创建无名管道#include unistd.h int pipe(int pipefd[2]);功能创建无名管道参数pipefd 用来存放管道两端的文件描述符pipefd[0] 管道读端pipefd[1] 管道写端返回值成功 0失败 -1管道特点1.管道大小64kb --- 65536个字节2.管道读写规则读端 写端存在 存在 ---写管道如果为空则此时可以写但是管道慢则写操作阻塞存在 存在 ---读管道如果管道有数据则读取如果没有数据则读操作会阻塞存在 不存在 ---读管道如果管道有数据则读取如果没有数据则读操作会直接返回不存在 存在 ---写管道管道破裂 //SIGPIPE --- 信号作用-结束进程3.管道中的数据是一个数据流读走之后就没有了其中的数据遵循FIFO的方式4.管道是一种特殊的文件 //也有以下操作read 、write 、close注意lseek --- 管道文件不能定位5.匿名管道无名管道用途用在亲属关系进程间通信 --- 父-子-孙6.管道是一种半双工的通信单工 数据发送方和接收方是固定的 eg广播单双工同一时刻只能有一个数据方向要么收要么发 eg对讲机全双工可以同时收同时发 eg电话手机匿名管道 --- 固定写端 和 固定的读端 数据方向单一父子进程间双向通信思路if (pid 0) { 从键盘输入数据 发给子进程 ---管道1 写端 从子进程中读取数据---管道2 读端 打印 }else if (pid 0) { 从父进程收数据 ---管道1 读端 打印 从键盘获得数据 ---管道2 写端 发给父进程 }有名管道特点1.符合管道特性a有大小b数据流的方向 --- 符合FIFOc管道读写规则2.有名管道也是一种特殊的文件a存在内存中b有名 --- 在文件系统中有名字类似于普通文件的名字c使用时可以当作普通文件操作open、read、write、close注意不能lseek定位3.用途任意进程间通信创建有名管道mkfifo //make fifo #include sys/types.h #include sys/stat.h int mkfifo(const char *pathname, mode_t mode);功能创建有名管道文件参数pathname 管道文件名mode 文件权限返回值成功 0失败 -1并且errno被设置注意有名管道进行通信时需要进行open操作如果只有一端以只读或只写的方式打开此时程序会阻塞在open操作必须等待另一端以相对的方式打开阻塞才会解除此时也表示有名管道文件 读端和写端都打开2.卸载管道remove();int unlink(const char *pathname);功能将指定的pathname管道文件卸载同时从文件系统中删除参数pathname 要卸载的有名管道返回值成功 0失败 -1测试有名管道文件读cat fifoname写echo hello fifoname软中断 //软件中断中断正在做A的过程中被B打断完成B后继续做A进程 ---- 信号中断 ----信号处理 ---- 中断信号处理1.默认操作2.忽略操作3.用户自定义的操作signal:#include signal.h typedef void (*sighandler_t)(int); sighandler_t signal(int signum,sighandler_t handler)功能设置对信号signum的处理方式函数参数signum 信号编号handler 信号处理函数SIG_IGN、SIG_DFL、自定义返回值函数指针 --- 信号处理函数的类型成功 返回上一次的信号处理函数的地址失败 返回NULL信号编号注意9SIGKILL和19SIGSTOP不能被忽视也不能被自定义信号处理函数void sighandler(int signo) { //signo 表示信号编号 对信号的处理 }在所有信号中有两个特例10 SIGUSR112 SIGUSR2是专门留给程序员使用的未定义信号 默认操作为kill进程和-9相同注意对一个信号反复注册后顺序注册则最后一个有效用途进行僵尸态的异步回收正常回收为wait阻塞等待、waitpid可以不阻塞signalSIGCHLD --- 子进程结束时发给父进程当父进程收到SIGCHLD信号时设置对应的处理函数在函数中回收资源kill#include sys/types.h #include signal.h int kill(pid_t pid,int sig);功能通过该函数可以给pid进程发送信号为sig的系统信号参数pid 要接收信号的进程sig 当前程序要发送的信号编号 --- kill -9返回值成功 0失败 -1raiseint raise(int sig) kill(getpid(),int sig)功能给调用进程发送sig信号alarmunsigned int alarm(unsigned int seconds); //SIGALAM功能定时由系统给当前进程发送信号也叫闹钟函数pauseint pause(void);功能进程暂停不再继续执行除非收到其他信号信号的通信不涉及大量的数据传递而是进程间运行时协作的一种通信IPC进程间通信方式1.共享内存2.消息队列3.信号量共享内存本质是内存中的一块预留空间直接对应的是一块物理空间IPCIPC通信方式使用时1.产生同一个key --- key值相同key使用ftok创建临时键值#include sys/types.h #include sys/ipc.h key_t ftok(const char *pathname, int proj_id);功能通过该函数可以将pathname指定的路径用来以proj_id生成唯一的临时键值参数pathname 路径名称 ---任意文件只要不被删除一般用/proj_id 整型的数字一般使用ASCII码的单字符返回值成功 返回唯一键值失败 -1ftok( / ,A);ipcs 查询共享内存申请对象shmget#include sys/ipc.h #include sys/shm.h int shmget(key_t key, size_t size, int shmflg);功能使用唯一键值key向内核提出共享内存使用申请参数key 唯一键值size 要申请的共享内存大小shmflg 申请的共享内存访问权限八进制表示如果第一个申请用IPC_CREAT --- IPC_CREAT|0666如果检测是否存在用IPC_EXCL返回值成功 返回共享内存id一般用shmid表示失败 -1shmat#include sys/types.h #include sys/shm.h void *shmat(int shmid, const void *shmaddr, int shmflg);功能将指定的shmid对应的共享内存映射到本地内存参数shmid 要映射的本地内存shmaddr 本地可用的地址如果不指定则用NULL表示系统自动分配shmflg 0 表示读写 SHM_RDONLY表示只读返回值成功 返回映射的地址一般等于shmaddr失败 (void *)-1撤销映射shmdt#include sys/types.h #include sys/shm.h void *shmat(int shmid, const void *shmaddr, int shmflg);功能将本地内存与共享内存断开映射关系参数shmaddr 要断开的映射地址 //shmaddr必须是前面shmat函数返回的地址返回值成功 0失败 -1删除对象shmctl#include sys/ipc.h #include sys/shm.h int shmctl(int shmid, int cmd, struct shmid_ds *buf);功能修改共享内存属性也可以删除指定的共享内存对象参数shmid 要删除的共享内存对象cmd IPC_RMID删除对象的宏buff NULL表示只删除对象返回值成功 0失败 -1
返回列表