Linux进程间通信操作

Linux进程间通信的方法
1、管道(pipe)
2、有名管道(named pipe)
3、信号量
4、消息队列
5、信号
6、共享内存
7、套接字
-------------------------------------------------------------------------------
linux进程间通信
1. 管道。
匿名一次性使用的,半双工。一个进程往输出端写管道,另一个进程从输入端读管道。
#include<unistd.h>
int pipe(int fd[2]);
fd[0]:表示读端
fd[1]:表示写端
2. FIFO特别文件
有名管道,作为特别文件存储于文件系统中。有名管道一旦建立就存在于文件系统中,除非显示的unlink
#include<sys/tpes.h>
#include<sys/stat.h>
int mknod(const char *path,mode_t mod,dev_t dev);
int mkfifo(const char *path,mode_t mode);
path:创建有名管道的全路径名
mod:创建有名管道的模式 ,指存取权限
dev:设备值,该值取决于文件创建的种类,它只在创建设备文件时才会用到
注意:有名管道创建后就可以使用了,有名管道和管道的使用方法基本是相同的。只是使用有名管道的时候必须先调用open()将其打开
因为有名管道是一个存在于硬盘上的文件,而管道是存在于内存中的特殊文件

3. 消息队列、信号量和共享内存
   函数 msgget semget shmget msgctl semctl shmctl
   消息队列、信号量和共享内存都是ipdc资源

   每个ipc资源有两个唯一的标志与其相连 关键字和标识(关键字类似于文件名,标志类似于文件描述字用来访问资源的操作)

   关键字获得函数 
   #include<sys/types.h>
   #include<sys/ipc.h>
   key_t ftok(const char * pathname,int proj_id);

   ipc_perm{              //结构,当进程创建ipc资源时,内核存储了ipc资源的属主和组id和访问权限等信息。
     uid_t uid            //当前有效用户id
     gid_t gid            //当前有效组id
     cuid_t cuid          //创建用户id
     cgid_t cgid          //创建组id
     mode_t mode          //访问权限
   };

   ipc资源创建之后,可以长期存储在文件系统中,直到被删除或者系统重启。
   shell命令:ipcs -q -s -m   ipcrm
       
   A、消息队列
   struct msqid_ds {            //消息队列相连的数据结构
     struct ipc_perm msg_perm; //该消息队列的属主和访问权限
     struct msg*    msg_first; //指向第一个消息的指针
     struct msg*     msg_last; //指向最后一个消息的指针
     msgqnum_t      msg_qnum;   //当前消息的个数
     msglen_t        msg_qytes; //最大容量字节数
     pid_t           msg_lspid; //最后一个调用msgsnd的进程
     pid_t           msg_lrpid; //最后一个调用msgrcv的进程
     time_t          msg_stime; //最后发送时间
     time_t          msg_rtime; //最后接收时间
     time_t          msg_ctime; //最后修改时间
   }

   struct msg {
    struct msg* mas_next; 下个消息的指针
    long msg_type;        消息的类型
    caddr_t msg_sport;    消息正文地址
    sort msg_ts;          消息正文的大小
   }

   int msgget(key_t key, int msgflg);
   key:为ftok函数的返回值
   msgflag:标志参数,可取值为IPC_CREATE,IPC_EXCL
   IPC_CREATE:当系统不存在和key相连的消息队列时,就创建一个key为关键字的消息队列(用于创建一个新的队列)
   IPC_EXCL: 和IPC_CREAT一起使用时,当已经存在队列时,则返回失败(防止关键字重复)

   int msgctl(int msgid, int cmd, struct msqid_ds* buf);
   控制消息队列cmd
   IPC_STAT   获得msgid的消息队列数据结果到buf中
   IPC_SET    设置buf中ipc_perm为消息队列的新值
   IPC_RMID   删除消息队列

   int msgsnd(int msgid, const void* msg, size_t size, int msgflag);
   mysgid:消息队列标识符
   msg:指向发送的消息
   size:要发送消息的大小,不包含消息类型占用的4个字节
   msgflag:操作标志位,可以设置为0或者IPC_NOWAIT
   0:当消息队列已满的时候,msgsnd将会阻塞,直到消息可以写进消息队列
   IPC_NOWAIT:当消息队列已满的时候,msgsnd函数不等待立即返回。
   msgsnd()为阻塞函数,当消息队列容量满或者消息个数满会阻塞,如果消息队列被删除,则EIDRM错误,被信号中断E_INTR。
              如果设置IPC_NOWAIT会返回-1并且置EAGAIN错误

   ssize_t msgrcv(int msgid, void* msg, size_t size, long int msgtyp, int msgflag);
   size实际上是指正文段的大小,总大小应该是size+4字节,接收是同样的意思
   msgtyp:请求读取的消息类型。
   msgflag: 操作标志位,可以为IPC_NOWAIT,IPC_EXCEPT,IPC_NOERROR
   IPC_NOWAIT:如果没有返回条件的消息调用立即返回,此时错误码为ENOMSG;
   IPC_EXCEPT:与msgtyp配合使用返回队列中第一个类型不为msgtyp的消息
   IPC_NOERROR:如果队列中满足条件的消息内容大于所请求的msgsz字节,则把该消息截断,截断部分将被丢弃
   long int msgtyp if == 0 接收第一个消息           
                    if > 0 接收类型等于msgtyp的第一个消息
                    if < 0 接收类型等于或者小于msgtyp绝对值的第一个消息


                           
B、信号量
struct semid_ds {
   struct ipc_perm sem_perm;       包含信号量资源的属主和访问权限
   struct sem      *sem_base;      指向信号量集合的指针
   unsigned short int sem_nsems; 集合中信号的个数
   time_t          sem_otime;      最后一次操作的时间
   time_t          sem_ctime;      最后一次修改的时间
}

struct sem {
unsigned short semval;           当前信号量值 
pid_t     sempid;                最后修改信号量的进程
unsignde short semcnt;           等待进行p操作的进程数
unsigned short semzcnt;          等待semval为0的进程数
}

int semget(key_t key, int semnum, int flag)
key:ftok函数的返回值
semnum:要创建的信号集包含的信号个数,如果只是打开信号集,其值为0即可
flag:标志参数,可取值为IPC_CREATE,IPC_EXCL,IPC_CREATE|IPC_EXCL
   IPC_CREATE:当系统不存在和key相连的消息队列时,就创建一个key为关键字的消息队列(用于创建一个新的队列)
   IPC_EXCL: 和IPC_CREAT一起使用时,当已经存在队列时,则返回失败(防止关键字重复)

信号量操作
int semop(int semid, struct sembuf* buf, int bufsize);
semid:信号集的标志符
buf:指向进行操作的结构体数组首地址
bufsize:指出将要进行操作的信号的个数

struct sembuf {
    short semnum; 信号量集合中的信号量编号
    short val;    val>0进行v操作加val,表示进程释放控制的资源;
                  val<0进行p操作减val,若没有设置IPC_NOWAIT,则调用进程阻塞,直到资源可用;否则进程直接返回EAGAIN 
                  val=0时阻塞等待信号量为0;若没有设置IPC_NOWAIT,调用进程进入睡眠状态,直到信号值为0;否则进程不会睡眠,直接返回EAGAIN
    short flag; IPC_NOWAIT IPC_UNDO当执行pv操作之后,进程突然终止没有进行相应的vp操作
}buf; 

semctl(int semid, int semnum, int cmd, union semun arg) 可以为信号量初始值,删除信号量设置权限等
semid:信号集标志符
semnum: 为信号量集合中的某个信号量操作
cmd:    SETVAL,IPC_STAT,IPC_SET,SETALL,GETALL,IPC_INFO,IPC_RMID
union semun {
   short val;              设置信号量的值SETVAL
   struct semid_ds* buf;   设置或者获得semid_ds结构IPC_STAT,IPC_SET
   unsigned short* array; 指向信号量的数组,用于集体初始化SETALL,GETALL
   struct seminfo *buf;    为控制IPC_INFO提供的缓存
} arg;
IPC_SET:对信号集的属性进行设置
IPC_RMID:把semid指定的信号集从系统中删除
GETPID:返回最后一个执行semop操作的进程的ID
GETVAL:返回信号集中semnum指定信号的值
GETALL:返回信号集中所有信号的值
GETNCNT:返回正在等待资源的进程的数量
GETZCNT:返回正在等待完全空闲资源的进程数量
SETVAL:设置信号集中semnum指定的信号的值
SETALL:设置信号集中所有信号的值

C、共享存储
shmget(key_t key, int size, int flag)
key:ftok返回的值
size:以字节为单位指定内存的大小
flag:标志参数,可取值为IPC_CREATE,IPC_EXCL,IPC_CREATE|IPC_EXCL
   IPC_CREATE:当系统不存在和key相连的消息队列时,就创建一个key为关键字的消息队列(用于创建一个新的队列)
   IPC_EXCL: 和IPC_CREAT一起使用时,当已经存在队列时,则返回失败(防止关键字重复)

size为n时表示获得或者创建这么大的共享段
size为0时表示直接获得整个共享段
size大于创建的共享段时,返回错误
(创建时指定n, 获得时一般直接为 0)
struct shmid_ds {
    struct ipc_perm shm_perm;
    size_t shm_segsz     大小
    pid_t shm_pid        最后操作的进程id
    pid_t shm_cpid       创建的进程id
    shmatt_t shm_nattch 当前连接数
    time_t shm_atime     最后调用shmat的时间
    time_t shm_dtime     最后调用shmdt的时间
    time_t shm_ctime     最后调用shmctl的时间
}
void* shmat(int shmid, const void* shmaddr, int flag);
shmid:共享内存区的标志符
shmaddr一般为0,内核自动为程序一个连接到共享内存段的地址返回给进程;共享内存的附加点
flag SHM_RDONLY SHM_RND(当shmaddr设置为自己的值时,shm_rnd标志设置后,将会对这个地址做适当的截断以适合系统的对齐)
参数shmaddr不同取值的含义如下:
    如果为空,则由内核选择一个空闲的内存区;如果非空,返回地址取决于调用者是否给flag参数指定了SHM_RND值,如果没有指定,则共享内存区附加到由shmaddr指定
    的地址;否则附加地址为shmaddr向下舍入一个共享内存低端边界地址后的地址(SHMLBA,一个常址) 
    通常将参数shmaddr设置为NULL

int shmdt(const void* shmaddr); //断开与共享内存区的联系
shmaddr:shmat的返回值
只有当shm_nattch为0后,即没有任何进程再使用该共享内存区,共享内存区才在内核中被删除,一般来说,当一个进程终止时,他所附加的共享内存区都会自动脱离

shmctl(int shmid, int cmd, struct shmid_d* buf);
shmid:共享内存区的标志符
cmd:IPC_STAT IPC_SET IPC_RMID SHM_LOCK SHM_UNLOCKroot用户专用
buf:指向shmid_ds结构体的指针

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值