Linux_进程间通方式

管道:半双工通讯
管道:借助文件系统在多个进程之间建立一条数据通讯信道,各进程通过自己打开的文件描述符操作同一块内存空间,从而完成数据的传递工作,管道的数据都是通过内存空间缓存的,像现实中的管道两端,一段进行读操作,一段进行写操作,如果管道为空,read会阻塞,如果管道为满则write会阻塞

有名管道:可以在任意进程间通讯,通讯是双向的,任意一端都可以进行读操作和写操作,但同一时间只能一端读,一端写
创建管道:int  mkfifo(const char *pathname, mode_t  mode);
打开管道:int  open(const char *pathname,  int flag);     
//仅仅打开,如果文件不存在不能创建,在仅一端打开时,open阻塞,直到有读端、写端,open才返回
写入数据:int   write(int  fd,  void  *buff,   size_t  size);
//read阻塞:管道中没有数据,管道中有数据但是写端关闭 
读取数据:int   read(int fd,  void  *buff,  size_t  buff_len);
//write阻塞:管道缓存区满,管道中有空间但是读端关闭
关闭管道:int   close(int  fd);

无名管道:只能在具有亲缘关系的进程(父子进程)间通讯,不能再网络间通讯,并且是单向的,只能一端读,一端写
创建及打开函数:int   pipe(int   fds[2]); 创建成功后,fds[0] 指向管道的读端    fds[1]指管道的写端 
写入数据:int   write(int  fd,  void  *buff,   size_t  size);
读取数据:int   read(int fd,  void  *buff,  size_t  buff_len);
关闭管道:int   close(int  fd);

有名无名管道区别
有名管道:可以在任意进程间通讯,通讯是双向的,任意一端都可以进行读操作和写操作,但同一时间只能一端读,一端写
无名管道:只能在具有亲缘关系的进程(父子进程)间通讯,不能再网络间通讯,并且是单向的,只能一端读,一端写
特点:通讯数据都遵循先进先出原则,并且都是半双工通讯,写入管道数据在内存存放
半双工通讯:同一通讯时刻,数据只能单方向传输
 

信号量 
信号量:类似于一个计数器,当信号量的值大于0时,记录临界资源的个数,当信号量等于0时,进程访问临界资源时必须阻塞,不实现数据的发送。
界资源:同一时刻只能被一个进程访问的资源
临界区:访问临界资源的代码区域
原子操作:不能被中断的操作,一旦开始,必须执行完成,中间不能被暂停
P、V 操作(对信号量的操作):P操作-1操作   V操作+1操作
进程同步:进程的执行必须按照一定的顺序执行。事情必须一步一步完成。
进程异步:进程的执行都是独立的,当一个异步调用发出后,调用者不能立刻得到结果时,进程不会阻塞,需要某些内核机制来通知其处理。

创建或获取信号量 :int   semget((key_t)key,  int  nsems,   int  flag);
初始化信号量:int   semctl(int  semid,  int  semnum,  int  cmd,  /*union  semun  arg*/);      cmd :  SETVAL
P、V操作:int   semop(int  semid,  struct  sembuf   semoparray[],  size_t  nops);
删除信号量:int  semctl(int  semid,  int semnum,  int  cmd);                                                cmd:  IPC_RMID

struct  sembuf {
unsigned  short  sem_num;
short sem_op;
short sem_flg;
};

操作系统对进程间的通讯用的信号量在内核中都是以信号量集管理的即就是通过semget函数获取到的是信号量集的标识符,其它函数操作时,必须指明操作的是那个信号量集中的那个信号量,类似于数组的下标

共享内存
共性内存:共享内存区域就是多个进程共享的一块物理内存地址,只是将这块物理内存分别映射到自己的虚拟空间上。假设存在10个进程将某块区域映射到自己的虚拟地址上,那么10个进程间就可以相互通讯,当一个进程向这块共享内存的虚拟地址写入数据时,其它的进程对这些数据是可见的。
实现原理:通过内核对象,将多个进程中的一个虚拟地址映射到内核对象所申请的一块物理内存上从而实现进程间数据的通讯。

两个进程的虚拟地址相等或者不相等,对于共享内存而言,无影响,虚拟地址需要通过进程页表,进行页面映射才能找到物理内存,共享内存共享物理内存空间
特点:多个进程操作同一块物理内存,所以进程必须同步执行 因为进程直接通过虚拟地址操作物理内存,所以不需要拷贝数据,共享内存是最快的一种进程间通讯方式

创建或获取共享内存int    shmget(key_t  key,   size_t   size,   int   flag);
连接到进程的虚拟地址空间:void  *  shmat(int  shmid,   const  void  *addr,    int  flag);
断开连接:int   shmdt(void  *ptr);
删除共享内存:int  shmctl(int  shmid,   int  cmd,   struct  shmid_ds   *buf);

共享内存是最快的IPC的原因:
在通讯之前,访问内核对象,需要用户态切换内核态,但是真正发送数据时,直接通过指针操作空间,不需要用户态切换内核态,共享内存可以直接通过指针将数据写到共享内存区域,接收方直接通过指针操作共享内存区域的数据,相比于管道消息队列少了两次数据的拷贝

消息队列
消息队列:是消息的链表,具有特定的存储格式,存放在内存当中,由消息队列标识符标识,消息队列允许一个或多个进程向他写入与读取数据,消息队列可以实现消息的随机查询,不一定要以先进先出的顺序读取,可按照类型读取,

创建或获取:int  msgget((key_t) key,   int  flag);
发送消息:int   msgsnd(int  msgid,  const  void *ptr,  size_t  nbytes,  int  flag);
                    ptr指向包含正的整形消息类型,在其后紧跟消息数据。
                    则可定义以下结构 struct  msgdata { long   type; char  text[512]; };
接收消息:int   msgrcv(int  msgid,  void  *ptr,  size_t  nbytes,  long  type,  int flag);
                    type:  指定要接收的消息的类型
                    type   > 0   返回队列中消息类型为type的第一个消息
                    type   == 0  返回队列中的第一个消息
                    type   <  0   返回队列中消息类型小于或等于type绝对值的消息,如果有多个,则返回类型值最小的消息
销毁消息队列:int  msgctl(int  msgid,   int  cmd,   struct  msqid_ds   *buf);
                           cmd:   当 cmd == IPC_RMID 时,销毁消息队列  

套接字 socket(预留)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值