进程间的通信

进程间的通信

历史:
     最初的unix IPC :   管道=pipe  FIFO 信号
     AT&T : 系统改进以及扩充形成 system V IPC (unix单个计算机内的进程通信) : system v 消息队列 信号灯 共享内存
     BSD :  基于socket的 IPC
     linux 则继承以上,并加入了posix
     POSIX : POSIX 表示可移植操作系统接口(Portable Operating System Interface :  posix 消息队列 信号灯 共享内存

概念:  
     信号signal : 通知其他进程某事发生(可用于通知自己) linux 支持 signal & signaction  。 信息量少
     message报文/消息队列 :消息链表,信息量大,有格式
     共享内存 : 效率最高,结合信号量使用,达到进程间的同步以及互斥 

进程的资源:
     一段程序
     内存中有进程控制块
     专用的系统堆栈空间
     独立的存储空间

 管道:

        1.半双工;   2. 父子进程间通信  int pipe(int filedes[2]);        // filedes[0]读, 1写
                    写端关闭时,读完了,则返回0;读端关闭时,仍然写,产生SIGPIPE信
                    实例:进程建立一个pipe, 然后调用fork生成一个子进程。父进程关闭读,子进程关闭写端。父进程读文件的内容写入写端
   子进程调用dup2,将读端复制到标准输入,并关闭该读端,然后exec使用分页程序从读中分页。
 
       TELL_WAIT等的管道实现,建立管道,等P,C的传递

  popen && pclose
   fout = popen(PAGER, "w");  // 往pageer程序中写东西,
   fputs(line, fout);
   pclose(fout);
  协同进程 coprocess
   一个add程序从标准输入中读a,b,把和C写到标准输出。这些输入输出都是从父进程的两个管道获得的,add称为协同进程
  setvbuf(stdin, NULL, _IOLBF, 0)
   fgets的标准输入是个管道时,默认为全缓存。即有一行输入时,也不返回。若此时作为协同进程,则无法工作
    setvbuf显示的使fgets等标准IO函数使用行缓存,立即返回。
    或者使协同进程认为调用它的是个终端
 FIFO
  命名管道
          mkfifo
(路径,模式同open)  // 创建后像文件一样可以用open, read等函数来处理,可以用stat来测试是否为FIFO类型
   O_NONBLOCK 无此标志时,只读阻塞到有写进程打开此FIFO;反之,一样
  用途:shell, 客服
   1) shell 用FIFO以及tee 将 infile-->prog1--->tee--->fifo--->prog3
         |--->prog2 
   mkfifo fifo1
   prog3 < fifo1 &
   prog1 < infile | tee fifo1 | prog2
   2)               
  
  
 系统V IPC : 消息队列 信号量 共享存储段
  IPC标示符从0增到最大
  创建IPC结构时(msgget, semget, shmget),需要指定key为长整数
  客户机和服务器在同一IPC结构上会合
   1)服务器用IPC_PRIVATE创建一个新的IPC,并把其标示符存到文件中给客户进程 
   2)服务器和客户机都用一个认可的key, 如果该key已经和一个现存的IPC, 则需要删除后再创建
   3)路径名 + 0~255 + ftok ==> key ,and 2)
  许可权 ipc_perm , 可使用(msgctl)修改
  缺点:要显示读取或者删除(msgrcv, msgctl),否则一直在系统中
 消息队列
  struct msqid_ds {许可权,上个消息,队列中消息个数,字节数}
  msgget
  msgctl(cmd   // cmd: 统计,设置,删除,eg IPC_STAT
  msgsnd(id, ptr, n, IPC_NOWAIT) // ptr = &struct mymsg{ long, char [512] }
  msgrcv( type // 可以通过type取消息

信号量 semaphore  // 实际创建的是进程或线程间通信的 信号量 的 集合
 semget(
key, 信号量的个数, flag==权限,创建)
 semop(key, &sembuf, 数组的大小) // sembuf = {信号量的索引,op == P V 操作申请释放资源, flag==不等返回 }
 semctl(key, 信号量个数,CMD,...) // ? 


 共享内存  mmap() vs shmget()
 key = ftok(filename, flag); // 将文件名转换为一个key
 shmid = shmget(key, size, flag); // 创建或得到一个共享内存的ID
 p_shm = shmat(shmid, null, flag); // 将共享内存映射到进程空间中
 shmdt()  // 将共享内存同进程分离
 shmctl() // 控制共享内存的属性等
 
 calllog example:
  (shmid = shmget((key_t)CONFIG_SHM_KEY, sizeof(call_log_file_t), IPC_CREAT | 0666)) < 0
  calllogfile_p = (call_log_file_t*)shmat(shmid, NULL, 0);
  
 比如,标准VGA 16色模式的实模式地址是A000:0000,而线性地址则是A0000。设定显存大小为0x10000,则可以如下操作 
      mem_fd  = open( "/dev/mem", O_RDWR ); 
      vga_mem = mmap( 0, 0x10000, PROT_READ | PROT_WRITE, MAP_SHARED,  mem_fd, 0xA0000 ); 
      close( mem_fd ); 
 然后直接对vga_mem进行访问,就可以了。 

 

15 高级进程通信
 流管道

          每端都是全双工  s_pipe(fd)     //  so fd[0]就可读写
          socketpair(AF_UNIX, SOCK_STREAM, 0, fd);
 传送文件描述符
  接受进程与发送进程共享同一个文件表项,但其对应的文件描述符不一定相同  // fd-->文件表-->V节点表(文件内容信息)
  send_fd
  send_err
  recv_fd
  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值