乐鱼电竞



  • 教育行业A股IPO第一股(股票代码 003032)

    全国咨询/投诉热线:400-618-4000

    C++培训之Linux 常见的六大IPC 通信方式(一)

    更新时间:2016年08月26日16时24分 来源:乐鱼播客C++培训学院 浏览次数:

    Linux 常见的六大IPC 通信方式
     
    Linux环境下,进程地址空间相互独立,每个进程各自有不同的用户地址空间。任何一个进程的全局变量在另一个进程中都看不到,所以进程和进程之间不能相互访问,要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓冲区,进程2再从内核缓冲区把数据读走,内核提供的这种机制称为进程间通信(IPC,InterProcess Communication)。今天我们来看一下,Linux下常见的六大IPC通信方式。   

    1、信号

        信号是Unix/Linux系统在一定条件下生成的事件。信号是一种异步通信机制,进程不需要执行任何操作来等待信号的到达。信号异步通知接收信号的进程发生了某个事件,然后操作系统将会中断接收到信号的进程的执行,转而去执行相应的信号处理程序。
    (1)注册信号处理函数
            #include <signal.h>
            /*typedef void (*sighandler_t)(int);  sighandler_t signal(int signum,sighandler_t handler);*/
     void (*signal(int signum, void (*handler)(int)))(int);  //SIG_IGN && SIG_DFL
          int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);
        (2)发送信号
            #include <signal.h>
            int kill(pid_t pid,int sig); //#include <sys/types.h> 
            int raise(int sig);            //kill(getpid(),sig);
            unsigned int alarm(unsigned int seconds); //(#include <unistd.h>) seconds秒后,向进程本身发送SIGALRM信号。
        (3)信号集
            信号集被定义为:typedef struct {unsigned long sig[_NSIG_WORDS];} sigset_t;
            * int sigaddset(sigset_t *set,int sig);
            * int sigemptyset(sigset_t *set);

    2、管道(Pipe)

        管道用来连接不同进程之间的数据流。
        (1)在两个程序之间传递数据的最简单的方法是使用popen()和pclose()函数:
            #include <stdio.h>
            FILE *popen(const char *command, const char *open_mode);
            int pclose(FILE *stream);
        popen()函数首先调用一个shell,然后把command作为参数传递给shell。这样每次调用popen()函数都需要启动两个进程;但是由于在Linux中,所有的参数扩展(parameter expansion)都是由shell执行的,这样command中包含的所有参数扩展都可以在command程序启动之前完成。
        (2)pipe()函数:
         int pipe(int pipefd[2]);
        popen()函数只能返回一个管道描述符,并且返回的是文件流(file stream),可以使用函数fread()和fwrite()来访问。pipe()函数可以返回两个管道描述符:pipefd[0]pipefd[1],任何写入pipefd[1]的数据都可以从pipefd[0]读回;pipe()函数返回的是文件描述符(file descriptor),因此只能使用底层的read()和write()系统调用来访问。pipe()函数通常用来实现父子进程之间的通信。
        (3)命名管道:FIFO
           int mkfifo(const char *fifo_name, mode_t mode);
        前面两种管道只能用在相关的程序之间,使用命名管道可以解决这个问题。在使用open()打开FIFO时,mode中不能包含O_RDWR。mode最常用的是O_RDONLY,O_WRONLY与O_NONBLOCK的组合。O_NONBLOCK影响了read()和write()在FIFO上的执行方式。
       

    3、信号量(Semaphores)

        System V的信号量集表示的是一个或多个信号量的集合。内核为每个信号量集维护一个semid_ds数据结构,而信号量集中的每个信号量使用一个无名结构体表示,这个结构体至少包含以下成员:
        struct{
            unsigned short semval;//信号量值,总是>=0
            pid_t sempid;  //上一次操作的pid
           …
        };
          (1)创建或访问信号量
           int semget(key_t key,int nsems,int flag);
        nsems指定信号量集中信号量的个数,如果只是获取信号量集的标识符(而非新建),那么nsems可以为0。flag的低9位作为信号量的访问权限位,类似于文件的访问权限;如果flag中同时指定了IPC_CREAT和IPC_EXCL,那么如果key已与现存IPC对象想关联的话,函数将会返回EEXIST错误。例如,flag可以为IPC_CREAT|0666。
        (2)控制信号量集
           int semctl(int semid,int semnum,int cmd,union semun arg);
        对semid信号量集合执行cmd操作;cmd常用的两个值是:SETVAL初始化第semnum个信号量的值为arg.val;IPC_RMID删除信号量。
        (3)对一个或多个信号量进行操作
         int semop(int semid,struct sembuf *sops,unsigned nsops);
         struct sembuf{
                  unsigned short sem_num;  //信号量索引
                  short   sem_op;     //对信号量进行的操作,常用的两个值为-1和+1,分别代表P、V操作
                  short   sem_flag;   //比较重要的值是SEM_UNDO:当进程结束时,相应的操作将被取消;同时,如果进程结束时没有释放资源的话,系统会自动释放
               };

    4、共享内存

        共享内存允许两个或多个进程共享一定的存储区,因为不需要拷贝数据,所以这是最快的一种IPC。
         (1)创建或访问共享内存
            int shmget(key_t key,size_t size,int shmflg);
        (2)附加共享内存到进程的地址空间
            void *shmat(int shmid,const void *shmaddr,int shmflg);//shmaddr通常为NULL,由系统选择共享内存附加的地址;shmflg可以为SHM_RDONLY
        (3)从进程的地址空间分离共享内存
            * int shmdt(const void *shmaddr); //shmaddr是shmat()函数的返回值
        (4)控制共享内存
           int shmctl(int shmid,int cmd,struct shmid_ds *buf);
           struct shmid_ds{
                  struct ipc_perm shm_perm;
                  …
              };
        cmd的常用取值有:(a)IPC_STAT获取当前共享内存的shmid_ds结构并保存在buf中(2)IPC_SET使用buf中的值设置当前共享内存的shmid_ds结构(3)IPC_RMID删除当前共享内存

     本文版权归乐鱼播客C++培训学院所有,欢迎转载,转载请注明作者出处。谢谢!
    作者:乐鱼播客C/C++培训学院
    首发:http://www.itcast.cn/c/ 
    0 分享到:
    和我们在线交谈!
    【网站地图】【sitemap】