进程间通信

        在Linux中进程间通信主要有:

               1.管道

               2.信号

               3.消息队列

               4.共享内存

               5.信号量

               6.套接字

       管道:

                管道分为有名管道和无名管道。无名管道只能用于亲属进程间的通信。它具有固定的读端和写端。有名管道可以实现两个互不相关的进程间通信。通过创建一个中间文件,然后两个进程操作这个中间文件。

                管道是一种特殊的文件,可以使用普通的read()、write()来操作它。就和操作普通文件一样,凡是它不属于任何文件系统,它存在在内存中。

 无名管道的创建:                   

int pipe(int fd[]);

        fd是包含两个元素的整型数组,存放管道对应的文件。

        函数成功返回0,失败返回-1。

        由于无名管道用于亲属进程,所以进程间共享内存资源,每个进程中都含有一对描述符fd[0]、fd[1]。所以必须关一个。要不传输数据混乱了。

        向管道写数据时,管道缓冲区只要有空间写进程就会试图向缓冲区写数据,如果缓存区满了,那么就会阻塞。

   有名管道的创建:

                

int mkfifo(const char* filename,mode_t mode)

filename:要创建的管道名。

mode:管道的访问权限

函数成功返回0,失败返回-1。

信号:

        信号是进程间通信机制中唯一的异步通信机制。

        进程可以通过三种方式来响应一个信号:

                1.忽略,对信号不做任何处理

                2.捕捉信号,定义信号处理函数,当信号发生时,执行相应的处理函数

                3.执行默认操作

        信号发送:

                

int kill(pid_t pid,int sig)

pid:正数:发送信号给进程为pid的进程

      0:信号被发送到所有和当前进程在同一个进程组的进程

      -1:信号发送给所有进程表中的进程

      <-1:信号发送给进程组号为-pid的每一个进程

sig:信号类型

成功返回0,失败返回-1。

kill不仅可以终止进程,也可以向进程发送其他信号。

int raise(int sig);

sig:信号类型

成功返回0;失败返回-1

定时器信号:

        

unsigned int alarm(unsigned int seconds);

second:系统经过second秒后向该进程发送SIGALARM信号。

注意:一个进程只能有一个闹钟时间,如果在调用alarm()之气那以设置过闹钟时间,则任何以前的闹钟时间都被新值所代替。

int pause(void)

函数返回-1,并把errno值设置为EINTR。

该函数用于将调用进程挂起直至接收到信号。

信号的设置:

        

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

signum:指定信号代码

handler:SIG_IGN忽略该信号

             SIG_DFL:采用系统默认方式处理信号

             自定义的信号处理函数

函数成功返回指向一个无返回值并且带一个整型参数的函数指针。失败返回-1。

该函数主要用于前32种非实时性信号的处理,不支持信号传递信息。

int sigaction(int signum,const struct sigaction* act,struct sigaction* oldset);

signum:信号类型,除SIGKILL和SIGSTOP之外的任何一个信号

 act:指向sigaction结构体的指针,包含对特定信号的处理。

oldact:保存之前的处理方式

成功返回0,失败返回-1。

信号量:

        信号量是用来解决进程/线程间的同步与互斥问题的一种机制。信号量对于某一种资源,取一个非负的整数值。信号量指的是当前可用的该资源的数量。若它等于0,则意味着目前没有可用的资源。

p操作:如果有可用的资源,信号量大于0,然后进入临界区资源后,信号量减一,如果没有可用资源,则会阻塞,信号量等于0,一直等到有资源时再被唤醒。

v操作:如果在该信号量的等待队列里有任务在等待资源,就唤醒一个阻塞任务,如果没有任务等待它,则释放一个资源,信号量减一。

        1.创建信号量或者获得系统已经存在的信号量,此时需要调用semget()函数。不同进程通过使用同一个信号量键值来获得同一个信号量。

        2.初始化信号量,此时使用semctl()函数的SETVAL操作。当使用二维信号量时,通常将信号量初始化为1。

        3.进行信号量的PV操作,此时调用semop()函数。这一步是实现进程之间的同步和互斥。

        4.使用semclt()函数的IPC_RMID操作从系统中删除信号量。

int semget(key_t key,int nsems,int semflag);

key:信号量的键值,多个进程可以通过它访问同一个信号量。

nsems:需要创建信号量的数目,通常取值为1。

semflag:同open()函数的权限位。

成功返回信号量标识符,失败返回-1。

int semctl(int semid,int semnum,int cmd,union semun arg);

semid:semget()函数返回的信号量标识符。

semnum:信号量编号,当使用信号量集时才会被用到,通常取值为0,表示使用单个信号量。

cmd:指定对信号量的各种操作

函数成功根据cmd返回不同的值,失败返回-1。

int semop(int semid,struct sembuf* sops,size_t nsops);

semid:semget()函数返回的信号量标识符。

sops:指向信号量的操作数组。

nsops:操作数组sops中的操作个数,通常取值为1,表示一个操作。

函数成功返回信号量标识符,失败返回-1。

共享内存:

        共享内存是最高效的进程间通信方式。因为进程可直接读写内存,不需要进行任何数据的复制。

        共享内存的实现分两步:

                1.使用shmget()创建一段共享内存。

                2.使用shmat()将这段共享内存映射到具体的进程空间。

                3.使用shmdt()解除映射。

int shmget(key_t key,int size,int shmflg);

key:共享内存的键值,多个进程可以通过它访问同一个共享内存。

size:共享内存区的大小。

shmflg:同open()函数的权限位。

成功返回共享内存段标识,失败返回-1。

char *shmat(int shmid,const void *shmaddr,int shmflg);

shmid:要映射的共享内存区标识符。

shmaddr:将共享内存映射到指定地址。为0系统自动分配。

shmflg:共享内存可读写设置。

成功返回被映射的段地址,失败返回-1。

int shmdt(const void *shmaddr);

shmaddr:被映射的共享内存段地址

成功返回0,失败返回-1。

消息队列:

        消息队列就有FIFO特性,但是它可以实现消息的随即查询,这些消息存在内核中,由队列ID实现。

        消息队列的实现步骤:

                1.使用msgget()函数创建或者打开消息队列。

                2.使用msgsnd()函数添加消息,它会把消息添加到已打开的消息队列的末尾

                3.使用msgrcv()函数读取消息,它会把消息从消息队列中取走。

                4.使用msgctl()函数控制消息队列。

int msgget(key_t key,int msgflg);

key:消息队列的键值,多个进程可以通过它访问同一个消息队列。

msgflag:权限标志位。

成功返回消息队列ID、失败返回-1。

int msgsnd(int msgid,const char* msgp,size_t msgsz,int msgflg);

msgid:消息队列的队列ID

msgp:只想消息结构的指针。

msgsz:消息正文字节数

msgflg:0表示msgsnd调用阻塞知道发送成功为止,IPC_NOWAIT表示若消息无法立即发送,函数立即返回。

成功返回0,失败返回-1。

int msgrcv(int msgid,void *msgp,size_t msgsz,long int msgtype,int msgflg);

msgid:消息队列的队列ID

msgp:消息缓冲区

msgsz:消息正文的字节数

msgtype:0表示接收消息队列的第一个消息

                 大于0表示接收消息队列中第一个类型为msgtyp的消息

                小于0表示接收消息队列中第一个类型值不小于msgtyp绝对值且类型值右最小的消息。

msgflg:0表示msgsnd()调用到阻塞直到接收到一条相应类型消息为止。

              IPC_NOWAIT表示在消息队列中没有相应的类型接收,直接返回。

              MSG_NOERROR表示若返回的消息比msgsz字节多,就截短到msgsz字节,且不通知消息发送进程。

成功返回0,失败返回-1。

int msgctl(int msgid,int cmd,strucr msgid_ds* buf);

msgid:消息队列的队列ID

cmd:IPC_STAT表示读取消息队列的数据结构msgid_ds,并将其存储在buf指定的地址中。

        IPC_SET表示设置消息队列的数据结构msgid_ds中的ipc_perm域值。这个值取自buf参数

        IPC_RMID表示从系统内核中删除消息队列列

buf:描述消息队列的msgid_ds结构类型的变量

成功返回0,失败返回-1。

 

最后,在Linux中使用ipcs命令查看进程通信机制状态。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值