Linux——进程(5)

一、进程通信

1、同一主机

1)、古老的通信方式
        管道:
           无名管道  
           有名管道  
        信号

2)、IPC对象通信
        消息队列(用的相对少,这里不讨论)
        共享内存(*)         //最高效 
        信号量集( )         //信号量  

2、不同主机 

1)、socket通信
         网络通信

3、举例

线程信号:
      posix  sem_init
特列:
      古老的通信方式中,信号是唯一的异步通信
      所有的通信方式中,共享内存是最高效的

管道:无名管道、有名管道

    无名管道 (pipe):只能给有亲缘关系进程通信
    有名管道 (fifo ) :可以给任意单机进程通信(同一主机内)

二、管道通信

1、管道的特性

    1)、管道是 半双工的工作模式
    2)、所有的管道都是特殊的文件不支持定位操作。
               lseek->> fd  fseek ->>FILE* 
               数据流 --- FIFO(first in first out)
    3)、管道是特殊文件,读写使用文件IO。
              fgets,fread,fgetc,
              open,read,write,close;;   

2、管道的读写规则

    1).读端存在,写管道
           管道空:可以写数据
           管道满(超过64k):会造成 写阻塞 
      
    2).读端不存在,写管道
           系统会给进程发一个信号SIGPIPE(管道破裂)

    3).写端存在,读管道
           管道空,读不到数据,
           这时会造成读操作阻塞

    4).写端不存在,读管道 
           如果管道中有数据,则读取这些数据!
           如果没有数据,读操作不阻塞,立即返回!

3、管道的使用

使用框架:
    创建管道         ==》        读写管道         ==》        关闭管道

1、无名管道         ===》        管道的特例         ===>pipe函数
    特性:
    1.1  亲缘关系进程使用
    1.2  有固定的读写端

    流程:
    创建并打开管道: pipe函数
    #include <unistd.h>
    int pipe(int pipefd[2]);
    int pipe(int *pipefd);
    int fd[2];
    功能:创建并打开一个无名管道
    参数:pipefd[0] ==>无名管道的固定读端//0 -- 标准输入
          pipefd[1] ==>无名管道的固定写端//1 -- 标准输出 
    返回值:成功 0
            失败 -1;

注意事项:
    1、无名管道的架设应该在fork之前进行。

1)、无名管道的读写

文件IO的读写方式。
    读: read()  
    写: write()

    关闭管道: close();

2)有名管道

fifo :有文件名称的管道。

框架:
    (1).创建有名管道 -- 类似 文件 (管道文件) 
    (2).打开有名管道 -- open 
    (3).读写管道     -- read/write 
    (4).关闭管道  ==》卸载有名管道 //close 

1、创建:mkfifo //创建了一个有名管道

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

2、打开有名管道 open
    注意:该函数使用的时候要注意打开方式,因为管道是半双工模式,                                                           所有打开方式直接决定当前进程的读写方式。
    一般只有如下方式:
    int fd-read = open("./fifo",O_RDONLY); ==>fd 是固定读端
    int fd-write = open("./fifo",O_WRONLY); ==>fd 是固定写端
    不能是 O_RDWR 方式打开文件。
    不能有 O_CREAT 选项,因为创建管道有指定的mkfifo函数
    
    有名管道打开:
    注意,如果一端是以只读,或者只写方式打开的。
    程序会阻塞,阻塞在打开操作。
    直到另一端,以只写或只读方式打开。

3、管道的读写: 文件IO

    读: read(fd-read,buff,sizeof(buff));
    写: write(fd-write,buff,sizeof(buff));

4、关闭管道:
        close(fd);

5、卸载管道:remove();
        int unlink(const char *pathname);
        功能:将指定的pathname管道文件卸载,同时
                   从文件系统中删除。
        参数: ptahtname 要卸载的有名管道 
        返回值:成功 0
                      失败  -1;

  6、有名管道的结论

    1)、是否需要同步,以及同步的位置。
             读端关闭 是否可以写,不能写什么原因。
              写端关闭 是否可以读。

        结论:
             有名管道执行过程过必须有读写端同时存在。
              如果有一端没有打开,则默认在open函数部分阻塞。

    2)、有名管道是否能在fork之后的亲缘关系进程中使用。
        结论: 可以在有亲缘关系的进程间使用。
        注意: 启动的次序可能会导致其中一个稍有阻塞。

    3)、能否手工操作有名管道实现数据的传送。
        读: cat  fifoname
        写: echo "asdfasdf" > fifoname

三、信号通信

    应用:异步通信。 中断   (软件中断)        1~64;32应用编程。

1、发送端

    int   kill(pid_t pid, int sig);
    功能:通过该函数可以给pid进程发送信号为sig的系统信号。
    参数:pid 要接收信号的进程pid
               sig 当前程序要发送的信号编号 《=== kill  -l
    返回值:成功 0
                  失败  -1;

    int raise(int sig)<==> kill(getpid(),int sig);  
    功能:给进程自己发送sig信号

    unsigned int alarm(unsigned int seconds);SIGALAM
    功能:定时由系统给当前进程发送信号
               也称为闹钟函数

                闹钟只有一个,定时只有一次有效,
                但是必须根据代码逻辑是否执行判断。


    int pause(void);
    功能:
             进程暂停,不再继续执行,除非
             收到其他信号。

2、信号(kill  -l)

         前32个有具体含义的信号(信号的含义详见图片)

3、接收端

        每个进程都会对信号作出默认响应,但不是唯一响应。
        一般如下三种处理方式:
        1、默认处理
        2、忽略处理 9,19
        3、自定义处理 9,19 捕获

        以上三种方式的处理需要在如下函数上实现。

    信号注册函数原型:
    typedef void (*sighandler_t)(int);
     ===》void (*xx)(int); == void fun(int);
     ===》xx是 void fun(int) 类型函数的函数指针
     ===》typedef void(*xx)(int)   sighandler_t; //错误
          
     sighandler_t signal(int signum, sighandler_t handler);
     ===> signal(int sig, sighandler_t fun);
     ===> signal(int sig, xxx fun);
     ===>fun 有三个宏表示:SIG_DFL 表示默认处理
                                             SIG_IGN 表示忽略处理
                                              fun     表示自定义处理

       void (*)(int) signal(int signum, void (*handler)(int) );

4、自定义信号处理

    1、必须事先定义自定义函数,必须是如下格式:
        void fun(int sig)          //sig 接收到的信息编号
        {

        }

    2、在所有的信号中有如下两个特列:
        10 SIGUSR1
        12 SIGUSR2  
        专门预留给程序员使用的未定义信号。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值