高级编程之进程间通信(一)

进 程 间 通 信

 

进程间通信:三大类
1、古老的通信方式
  无名管道
  有名管道
  信号  ====》唯一的异步通信方式

2、systemV  IPC 对象
  消息队列
  共享内存  ===》效率最高的通信方式
  信号量集

 

3、BSD socket 套接字
  域内套接字  ==》单机进程间通信
  网络套接字  ==》不同主机上的进程间通信

古老的通信方式:
1、管道  ==》无名管道  有名管道

 无名管道 ==》pipe

 1、特性
  只能用于具有亲缘关系的进程间使用。
  半双工的通信模式,有固定的读写端。
  属于特殊的设备文件,只能用文件IO读写。
  该类型的文件不支持定位操作。

 2、使用流程
 创建管道===》打开管道 ===》读写管道 ==》关闭管道
   pipe()           read()/write()  close()


 头文件: #include <unistd.h>

 原型: int pipe(int fd[2]);
 功能:该函数可以创建一个无名管道,
       并且自动打开该管道。
 参数: fd[2] 管道的读写端,有如下默认约定
    fd[0] 固定的读端
    fg[1] 固定的写端
 返回值:成功  0
   失败  -1;

 读: read
 写: write()


 关闭: close()



有名管道  ===>fifo  ===>在无名管道基础之上增加了一个文件名称
      方便在不同进程间使用。

操作流程:
 创建有名管道 ===》打开管道 ===》读写管道 ==》关闭管道 ===》卸载管道。
 mkfifo              open        read/write    close        unlink


1、创建有名管道 ==》mkfifo

#include <sys/types.h>
#include <sys/stat.h>

int mkfifo(const char *pathname, mode_t mode);
功能:在指定的pathname路径下创建一个权限为mode的有名管道。
参数:pathname 要创建的有名管道的路径+管道名称
   mode  要创建的管道文件权限。
返回值:成功  0
  失败  -1;


***** 注意:
所有的管道都是设备文件,同时该设备文件有固定的读写端。
  open();的参数2 不能是 O_RDWR,只能是O_RDONLY 或者 O_WRONLY 之一

 

 

#include <unistd.h>

int unlink(const char *pathname);
功能:通过该函数可以完成指定的有名管道卸载。文件会被删除。
参数:pathname 要卸载的管道
返回值:成功  0
  失败   -1;

注意:unlink函数一般用于最后管道没有人使用的时候卸载用。


一般为了有名管道的配合使用。管道的创建工作可以独立执行
或者在读端启动的时候首先创建。


练习:
1、从a.out程序中读取指定文件内容通过有名管道发送到b.out
   并从 b.out 中打印输出。

2、测试有名管道能否在fork之后的父子进程间使用。


注意:一般在项目中需要有一个有名管道的维护工具,
  可以动态的手工创建并删除管道.比如:
  fifo_tool 名称
  功能: fifo_tool -A abc   ===>在当前路径下新建一个名称为
         abc 的有名管道
   fifo_tool -D abc   ===》删除当前路径下名称为abc的管道。

 

信号通信:====》传递的是信号 ,而不是数据.

通信框架:  发送端进程 ===》信号 ===》接收端进程


1、发送端进程 ===》函数: kill()  raise()  alarm ()  pause()

#include <sys/types.h>
#include <signal.h>

原型:int kill(pid_t pid, int sig);
功能: 通过该函数可以给指定的pid进程发送sig编号的信号。
参数: pid 要接受信号的进程pid号
      sig 要接受的信号。
返回值:成功 0
  失败  -1;

原型: int raise(int sig);
功能: 进程自身给自己发送一个sig信号。
参数: sig 发给自己的信号编号
返回值:成功 0
  失败  -1;

头文件  #include <unistd.h>

原型: unsigned int alarm(unsigned int seconds);
功能:定时由OS给当前进程发送一个定时信号SIGALRM
   默认该信号会杀死进程。
参数:seconds  程序从当前函数开始后seconds秒后会
  收到来自OS的SIGALRM信号。
返回值:成功  0
  失败   -1;


原型:int pause(void);
功能:使当前运行的进程暂停。
返回值:成功  0
  失败   -1;

2、信号  ===》kill  -l 中前32个不稳定信号。

  
3、接受端进程 ===》进程收到信号的处理过程:

 每个进程对信号有三种处理方式:
  1、默认处理
  2、忽略处理
  3、自定义处理

信号的注册函数: ==》signal  函数

原型:
 void (*signal(int signum,void (*handler)(int)))(int);

===>void (*xxx)(int aa);===>函数指针
    xxx == signal(int signum,void(*handler)(int));

===>typedef void (*sighandler_t)(int);

   sighandler_t signal(int signum, sighandler_t handler);
 
   signal(int signum,fun); ===>信号注册函数

   其中:signum 表示要处理的信号编号
      fun 表示信号的处理方式:
     如果fun == SIG_IGN ===>表示忽略处理方式
       SIG_DFL ===>表示默认处理方式
      函数地址 ===》自定义函数‘

重要:在所有的信号中9 号的SIGKILL 和  19 号的 SIGSTOP
      信号不能被忽略。同时也不能被修改。


特殊:10  SIGUSR1
   12  SIGUSR2
   以上两个信号在所有32个信号中是唯一的两个没有具体
   含义的临时信号,预留给程序员编程使用。

练习题:
 编写信号处理程序,当收到10号和12号信号的时候启动不同的程序。
 其他信号都按默认处理流程。

 

 

 

 

 

 

 


 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章