Linux编程---进程通信

Linux的通信方式主要有分类有下面几种:

-匿名管道和FIFO有名管道

-消息队列,信号量和共享存储

-套接字

.对于套接字的进程通信,我就留在套接字的文章中再写了.

一.管道

管道是最古老的进程通信机制了.提供进程间的单向通信.

1.创建管道

int pipe(int fdes[2]);

实际上管道通过参数返回读和写的两个文件描述符.相当于是打开了两个文件吧.但是这个文件是特殊的pipe文件.fdes[0]表示的是输入,fdes[2]表示的是输出.注意,这个函数只创建一个文件,而不是创建两个文件一个用来读,一个用来写.

管道创建调用成功,那么就返回0,否则返回-1,并设置errno错误条件.

如果向写文件描述符进行读,那么会生成一个SIGPIPE信号,并且当信号被阻塞是将以EPIPE错误失败.管道文件不允许文件定位,读和写操作都是顺序的,读从文件的开始处读,写则写至文件尾.

这么看似乎好像没有和别的进程关联起来.实际上,管道单独使用的话只是创建了两个文件而已,想要使用管道还得使用fork,exec,dup等函数来创建一个进程才能使用.

简答来说,对于创建的进程来说,其读写的文件是相反的.并且对于管道来说,其方向只能是单向的,所以如果你创建了新进程,两个进程至少要关闭一个文件描述符.

2.popen和pclose函数

这两个函数是C标准库中的两个函数.并且创建的方式也比系统调用方便.

FILE *popen(const char *command,const char *mode);

int pclose(FILE * stream);

第一个函数通过第一个参数,解析其命令建立一个新进程.过程就是先建立一个管道,然后派生一个子进程,调用exec启动一个shell程序执行command给出的命令.并立即返回一个管道对应的流指针.

mode的方式只能是”r”和”w”两种方式之一,但是不能两个一起,所以这和一般的文件模式是不同的.

这么来看,这个函数就比用上面的pipe系统调用方便得多.封装了包括fork,exec,dup等一系列调用~当然,这个函数相对自己调用pipe+fork+exec+close来说效率就要差一些了.

管道IO的原子性

实际上管道就是一片内存缓冲区.(我记得原来学的时候创建一个管道,然后在图形界面下把管道文件给删了,但是管道仍然正常使用).所以如果写入管道的数据块大小超过这片缓冲区的大小时,内核就要分几次写入了.如果是分批写的话,那么就很可能造成混乱了.试想如果A进程需要分3次写,在写完第二次的时候时间片到了,切换到另外一个进程也要往这个管道写内容,那么就可能导致内容产生混乱.(可以fork出多个子进程向同一个管道进行写操作给父进程数据).如果是一对一的关系就无所谓了,但是对于一对多就需要注意了.

管道缓冲区的大小由定义在头文件<limits.h>中的宏PIPE_BUF给出.在Linux系统中其值为4096.并且一旦写入PIPE_BUF个字节至管道后,进一步写管道的操作将阻塞直到有些字节已读出.

二.FIFO特别文件

由于管道只能用于存在父子关系的进程之间的通信,为了满足非父子进程关系下的通信.可以用FIFO特别文件.

FIFO特别文件类似于管道,也是半双工方式,并且数据也是按先进先出顺序传送,因此的名FIFO.但是创建的方法与管道不同,管道式匿名通信通道,而FIFO特别文件通过调用mknod()被等级到文件系统,因此FIFO有时也成为有名管道.

与管道的主要不同有:

--FIFO作为特别文件存在于文件系统中

--不同祖先的进程可以通过FIFO特别文件共享数据

--当共享进程完成了所有IO操作后,除非unlink删除它,否则FIFO特别文件将存在文件系统中,并且可以留待下一次使用.

创建了FIFO文件之后,对于任何进程,只要知道了其名字并且有适当的访问权限,就能按照正常文件相同的方法打开它读或者写.

在某个进程读之前,必须有进程表示以写的方式打开这个文件,否则读进程则会一直阻塞.

同理,在写之前也一定要有进程打开了读,否则一样阻塞.

1.创建FIFO文件

int mkfifo(const char *path,mode_t mode);

int mknod(const char *path,mode_t mode,dev_t dev);

mkfifo创建一个FIFO特别文件,用参数path来指定其路径和文件名.mode参数则用来设置文件的权限.取值和open函数一样.

mknod创建一个给定文件类型的新文件,path同mkfifo.文件类型由mode参数给出,可选的值如下:

S_IFIFO  这个就是特别文件

S_IFCHR  字符特别文件(不可移植)

S_IFDIR   目录文件(不可移植)

S_IFBLK   块特别文件(不可移植)

S_IFREG   普通文件(不可移植)

除开这些个参数,mode还需要另外附加上文件的访问方式,用获得方式组合宏定义.mknod似乎是比mkdir之类函数更底层的函数.

并且这个mode还受umask的修正,对于mkfifo则不受其影响.

由于刚打开时可能造成阻塞(读方式打开没有写进程,写操作打开没有读进程),并且打开文件的时候可以用O_NONBLOCK标志.第一次操作这个文件,并且打开方式使用了O_NONBLOCK的时候,open函数会返回-1,并且设置errno为错误值.

2.读写FIFO文件

和管道不同,由于打开FIFO文件可以使用O_NONBLOCK标志.所以要复杂一些.

没有O_NONBLOCK的时候读,如果没有可以读的,那么就会阻塞.有O_NONBLOCK的话,那么就直接返回-1,并且设置errno为EAGAIN了.

正常情况下如果文件写满了再调用write,那么会一直阻塞,知道信息被读走.完成操作时,返回写入的字节数.当用了O_NONBLOCK打开的时候,那么不能写则会返回-1,表示没有写进任何数据.errno也设置为EAGAIN.

原子性和管道一致.对于多个写一个读的时候,最好保证write的进程是不没有使用O_NONBLOCK的.并且每次写的时候,写入的数据小于PIPE_BUF的大小.保证写入数据的完整性.

三.系统V 的IPC

这个主要有三种进程通信方式:消息队列,共享存储,信号量

每一个IPC资源有两个唯一的标志与之相连:关键字和标识.

1.关键字

类型是一个key_t的长整型.用来命名要使用的IPC资源,以便可以被多个进程引用.进程通过指定一个关键字调用xxxget()函数可获得一个IPC资源的标识,就像指定文件名调用open获得文件描述字一样.

其取值可以为:

IPC_PRIVATE:其值一般为0.表示总是创建一个新的IPC资源.可以用过xxxget()函数来获得.并且其他进程不可能通过xxxget来获得一样的关键字.但可以通过其他途径获得其标识来访问它.另外,对于进程的子进程是共享这个标志的.

非零值: 表示这个队列可以被多个进程使用.

为了方便应用能像文件一样用路径名来表示IPC资源,C标准库中提供了一个函数ftok可以将文件名转换wei 关键字.

key_t ftok(const char *path,int id);

ftok将根据path和id返回一个类型为key_t的关键字,该关键字可以作为msgget,semget,shmget函数的IPC资源参数.

path参数必须是一个已经存在的文件路径名.id只有低8位有效.如果id的低8位为0,那么ftok的行为不确定.

ftok返回的关键字是根据文件的inode号来确定的.如果文件在删除后又重新创建,那么ftok返回的关键字也会改变,尽管参数一样.

2.标识

每一个独立的消息队列,信号量集合和共享存储段都由一个唯一的正整数所标识.如果说关键字类似于文件名,那么表示就类似于文件描述字.

标识对于不同类型是独立的.也就是消息队列和信号量的都有一个标识,那么这两个类型标识值可以相同.

3.IPC资源描述结构与成员ipc_perm

每个IPC的属主在创建这个资源之后,这个资源可以被属主自己或root用户调用IPC控制函数xxxctl将这个IPC资源的所有权转让给其他进程.新的进程将成为这个IPC的当前属主.但创建者仍然保持不变.

每个IPC资源被创建时,内核会在系统内部创建它的标识和一个类型为xxxid_ds的数据结构与之相连,并存储它的用户,用户组以及其他人的读写全县信息于xxxid_ds的成员xxx_perm中.xxxid_ds为IPC资源描述,与消息队列,共享存储,信号量表示相连的IPC资源描述分别是msgid_ds,shmind_ds,semid_ds.

ipc_perm结构体中有一下一些成员

uid_t uid       IPC资源当前所有者的用户ID

gid_t gid       IPC资源当前所有者的组

cuid_t cuid     IPC资源创建者的用户ID

cgid_t cgid     IPC资源创建者的组ID

mode_t mode   读写许可权限.

mode和文件的权限类似.包括自己,组和其他人的一些权限.但和文件不同的是执行权限一般为0.因为对于IPC来说没有意义.具体有哪些宏可以百度mode_t这个类型.

由于资源可以在进程结束后仍然存在.所以也可以通过命令来查询和删除资源

ipcs和ipcrm两个shell命令就是用来查询资源和删除资源.

两个命令用-q,-m,-s来指定类型.

四.消息队列

消息队列类似FIFO.也是半双工的,只能单向.但是和FIFO不同,对于消息队列其信息是离散的,一段一段的信息.这些信息可以有不同的结构和优先级.这样通信的方式也更灵活了.实际上消息队列是内核地址空间的内部链表.

对于消息队列而言,内核维护一个msqid_ds数据结构,记录了消息队列的特征和当前状态.虽说是内核空间的东西,但是对于应用而言会常常访问它.结构中的成员如下:

struct ipc_perm msg_perm   操作许可权限数据结构指针

struct msg *msg_first       指向队列中第一条消息的指针

struct msg *msg_last        指向队列中最后一条消息的指针

pid_t msg_lspid           最后一个发送消息的进程ID

pid_t msg_lrpid           最后一个接受消息的进程ID

time_t msg_stime          最后一条消息的发送时间

time_t msg_rtime          最后一条消息的接受时间

time_t msg_ctime          最后的改变时间

unsigned short msg_qnum    队列中当前消息个数

unsigned short msg_qbytes   队列中所允许的最大字节个数

unsigned short msg_cbytes   队列中当前字节数

这些结构体信息可以用msgctl来查看.

消息正文存放在用户分配的消息缓冲区中被发送和接受.消息缓冲区是一个结构,系统除了要求它的第一个成员必须是long int类型且值大于0外,对其他成员不做限定.第一个成员给出消息类型.通常,我们将消息缓冲区十位一个msgbuf类型的结构,并把它看作是所有消息的模版,如下所示:

struct msgbuf{

long int mtype;  消息类型

char mtext[1];   消息正文

}

1.创建和获得消息队列

int msgget(key_t key,int flags);

参数key就是队列的关键字;参数flags除开文件权限的宏外,还有以下两种宏

IPC_CREAT: 如果不存在与key相连的IPC资源,创建它:若未指定IPC_CREATE且系统中不存在相同key值的IPC资源,shmget()将失败返回

IPC_EXCL: 若已经存在与key相连的IPC资源,调用失败.

如果是调用来创建一个新的消息队列,那么内核会创建一个msqid_ds结构.msqid_ds结构成员msg_perm包含属主信息和访问权限.

将key值指定为IPC_PRIVATE,msgget将总是创建一个消息队列.如果在flags中设置IPC_CREAT标志.同样也会创建新队列.单独设置IPC_EXCL没有作用,它与IPC_CREAT一起用来保证不会打开一个已经存在的队列.如果只指定IPC_CREAT,msgget要么返回新创建的消息队列ID,要么返回具有相同key值的消息队列ID.

当flags为0时,可以用来得到与key相关的进程ID.

2.消息队列的查询,设置和删除

int msgctl(int msgid,int cmd,struct msqid_ds *buf);

msgctl对消息队列msqid执行参数cmd要求的控制操作.cmd可以取以下值:

IPC_STAT: 复制消息队列的内核数据机构msqid_ds到buf所指用户区.此命令用于查看消息队列的状态

IPC_SET: 用buf结构中给出的值设置消息队列msqid内核数据结构中成员msg_perm的uid,gid,mode,qbytes的值.此命令用于改变消息队列状态.

IPC_RMID: 删除msqid指定的消息队列

这些命令中,对于STAT来说,必须具有消息队列的读权限.执行IPC_SET和IPC_RMID命令的进程只能是消息队列的创建者,拥有或特权进程.此外,只有特权进程才可以增大消息队列的字节数.

如果msgctl调用成功返回0,否则返回-1并设置errno.

3.发送和接收消息

int msgsnd(int msqid,const void *msgp,size_t msgsz,int msgflg);

ssize_t msgrcv(int msqid,void *msgp,size_t msgsz,long int msgtyp, int msgflg);

两个函数中参数msqid必须为消息队列ID.第二个参数msgp是指向用户消息缓冲区的指针.消息缓冲区应当指定为上面说的msgbuf类型的结构体(我觉得既然已经确定按某种形式来分析消息了,为什么还要用void*...).并且消息类型实际上就是优先级.第三个参数就是正文的大小了,而不是整个结构体的大小必须大于0且小于系统限制值MSGMAX..

1)发送消息

msgsnd向消息队列msqid发送一条消息.要发送的消息存放在msgp所指用户消息缓冲区中.

当在以下情况时,msgsnd会阻塞

--消息队列中的总字节数已等于msg_qbytes()

--系统中所有消息队列中的消息总数已达到系统施加的限制值.

从阻塞返回也有以下几种情况:

--消息可以被发送了...

--消息队列已经从系统中删除.此时会设置errno为EIDRM并且返回-1.

--调用进程收到一个信号.调用被中断,设置errno为EINTR并返回-1.

和一般IO一样,可以通过msgflg来设置为不阻塞的状态IPC_NOWAIT.当发生阻塞时,消息不被发送,调用将设置errno为EAGAIN并立即返回.

2)接收消息

这个函数就是msgsnd的反过程.主要说明一下第四个和第五个参数

第四个参数指明要接受的消息类型.

=0 接受队列中的第一个消息.即顺序接受消息

>0 接受类型等于msgtyp的第一个消息.只用于接受某种特定类型的消息.感觉和=0的情况差不多吧.

<0 接收类型小于或等于msgtyp绝对值的第一个最低类型的消息.用于接收优先消息.也就是说消息中的第一个long int的值越小优先级越高.

第五个参数msgflg指明所系统的消息不在队列时,以及接受消息大小大于msgsz给定值时采取的动作.它有两个宏:

MSG_NOERROR: 表示消息过大的时候自动截断.否则未使用时将设置errno为E2BIG

MSG_NOWAIT: 表示接收消息并不阻塞.

阻塞的状况下错误和msgsnd的形式一样.

五.共享存储段

共享存储段是通过内存来共享信息内容.这个方式是最快的,但是其本身并不提供任何同步,所以写代码会麻烦一些.可以用后面的信号量一起使用.

1.创建和获得共享存储段

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

key和消息队列一样.用IPC_PRIVATE表示创建一个私有共享存储段,其他情况函数的动作还取决于shmflg中的IPC_CREAT和IPC_EXCL..

类似的shmflg可以设置除IPC_CREAT和IPC_EXCL外,还可以设置权限.

调用成功的话,返回与key相关的存储段ID.同时key相连的数据机构shmind_ds结构成员如下:

struct ipc_perm shm_perm   操作稀客权限数据结构指针

size_t shm_segsz           共享存储段的大小,单位为字节

pid_t shm_lpid            最后对共享存储进行操作的进程pid

pid_t shm_cpid            创建进程的ID

shmatt_t shm_nattch        当前连接数number of current attaches

time_t shm_atime          最后调用shmat的时间

time_t shm_dtime          最后调用shmdt的时间

time_t shm_ctime          最后调shmctl的改变时间

2.共享存储段的查询,设置和删除

int shmctl(int shmid,int cmd,struct shmid_ds *buf);

shmid即共享段的标志.参数cmd指定操作,与消息队列的情况类似,cmd的取值可以是IPC_STAT,IP_SET和IPC_RMID.对应查询,设置和删除.对于查询要具备读权限.对于SET而言,并不影响已经连接了该共享存储段的进程读写权限.对于RMID来说,调用之后不允许进程再与其连接,共享段仍然存在,直到最后一个连接进程与其分离之后才从系统中删除.这时如果有新进程连接这个段,那么会重新创建一个段.

调用成功返回0,否则返回-1并设置errno.

3.共享存储段的连接和分离

创建共享段时,我们并不知道其共享段的地址.实际上在创建之后还涉及一个连接和分离的过程.

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

int shmdt(const void *shmaddr);

前一个函数是连接,后一个是分离.

对于第一个函数来说,shmid是其共享段ID.shmaddr则是用来指定共享段地址,可以是0让系统分配,也可以是一个地址值.通常就填写为0了.如果是地址值,通常要是页面的整数值.

shmflg可以设置两个宏:

SHM_RND: 设置这个标致之后,对于shmaddr为非0的时候,实际的地址会变成shmaddr-(shmaddr%SHMLBA)这个值.SHMLAB是系统定义的共享存储最小对齐边界大小.

SHM_RDNOLY: 存储段是只读的.

对于第二个分离函数来说.分离并不一定会导致共享段被删除.调用了shmctl并设置IPC_RMID之后并且连接数为0才会删除共享段.实际上当进程结束的时候,系统也会自动的分离共享段.

当连接之后,进程就可以通过地址,把其当作一个大数组来用了~

六.信号量

信号量就是可以多次计数的一种同步方式.而互斥量则是只有0和1.

semid_ds结构成员如下:

struct ipc_perm sem_perm;   操作许可权限数据结构指针

struct sem *sem_base;       指向信号量集合的指针

unsigned short int sem_nsems;   集合中信号量的个数

time_t sem_otime;           最后一次操作的时间

time_t sem_ctime;           最后一次改变此结构的时间

sem结构成员

unsigned short semval;       信号量当前值

pid_t sempid;              最后操作该信号量的进程ID

unsigned short semncnt;     等待对该信号量执行P操作的进程数

unsigned short semzcnt;     等待semval=0的近成熟

1)创建和获得信号量标识

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

key与semflg和上面的共享内存一样,.这里主要写一下nsems指明信号量集合中信号量的个数.(注意是集合,而不是单个信号量!!!)并且这个值是有限制的.必须大于0且小于SEMMSL.Linux中默认值为250.当key所指定的信号量集合已经存在时,nsems必须为0,或者大于集合原来的信号量数.否则调用失败.一般取0就可以了.

返回值为信号量的ID,即标识.

2)信号量的查询,设置和删除

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

第一个参数指定标识ID,第二个则是信号集合中的第几个信号.cmd则是操作.第四个参数比较特别,它是可选的.结构如下

union semun{

int val;    用于SETVAL命令,指明要设置的信号量值

struct semid_ds *buf;  用于IPC_STAT/IPC_SET命令,指向存放信号量集合数据结构的缓冲区

unsigned short *array;  用于GETALL/SETALL命令,存放所获得的或要设置的信号量集合中所有信号的值.

}

cmd命令有以下一些选项:

SETVAL  设置单个信号的值    用arg.val

GETALL  返回信号量集合中所有信号量的值   arg.arry

SETALL  设置信号量集合中所有信号量的值   arg.arry

IPC_STAT  放置与信号量集合相连的semid_ds结构的当前值于arg.buf指定的缓冲区

IPC_SET   用arg.buf指定结构值替代与信号量集合相连的semid_ds结构值

GETVAL   返回单个信号量的值

GETPID    返回最后一个操作该信号量集合的进程ID

GETNCNT   返回semncnt的值

GETZCNT   返回semzcnt的值

IPC_RMID   删除指定的信号量集合

通常常用的就SETVAL和IPC_RMID.对于其他的完全可以写个函数封装起来...

调用这个函数要注意两点:

---对于不同命令,semctl要求不同的参数,其中有的参数可能是无用的,应当指定参数值为0.

---联合semun的成员buf和array均为指针,在使用之前一定要指向一个可用空间.

3)信号量操作

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

第一个参数即信号集合标识,第二个参数sembuf结构的成员如下:

unsigned short int sem_num;  信号量编号

short int sem_op;           信号量操作

short int sem_flg;            操作标志

op有以下取值

<0  减少一个信号量额值.减少量为其绝对值.当不够减时,则阻塞,直到足够减.

=0  等待信号量变为0.一直阻塞直到为0.

>0  增加一个信号量的值.增加量就是其大小.

sem_flg有以下标志:

IPC_NOWAIT: 表示不阻塞

SEM_UNDO: 当进程退出时,执行信号量解除操作.对于指定了这个宏的信号量,内部有一个semadj变量与之相连,它的作用是在进程死亡时调整信号量的值.也就是如果一个信号量的值减少了x,那么它就加上semadj;反之则减少semadj.设置了这个宏之后,对这个信号量的反操作也要设置SEM_UNDO.这样才能保证最后信号量能恢复到0.

最后第三个参数则是指定第二个参数有多少个struct sembuf元素.取值范围为0~SEMOP.其中SEMOP是一个可配置的系统参数,规定了单个semop调用允许的最大操作个数.

只有当集合中所有信号量操作都能成功时才成功返回,且返回值为0.如果集合中某个信号量操作不能完成,则所有操作都不会执行.如果操作没有设置IPC_NOWAIT则会一直阻塞.直到以下一种情况发生:

--所有操作完成.

--进程收到一个信号

--信号量集合被删除.

内核会保证任何时刻只有一个进程能够操纵信号量集合.如果多个进程发送操作请求,那么内核会一个个的响应,但是顺序是随机的.

Linux编程---进程通信

时间: 2024-10-22 19:07:59

Linux编程---进程通信的相关文章

Linux系统编程@进程通信(一)

进程间通信概述 需要进程通信的原因: 数据传输 资源共享 通知事件 进程控制 Linux进程间通信(IPC)发展由来 Unix进程间通信 基于System V进程间通信(System V:UNIX系统的一个分支) POSIX进程间通信(POSIX:可移植操作系统接口,为了提高UNIX环境下应用程序的可移植性.很多其他系统也支持POSIX标准(如:DEC OpenVMS和Windows).) 现在Linux使用的进程间通信方式包括: 管道(pipe).有名管道(FIFO) 信号(signal) 消

Linux之进程通信20160720

好久没更新了,今天主要说一下Linux的进程通信,后续Linux方面的更新应该会变缓,因为最近在看Java和安卓方面的知识,后续会根据学习成果不断分享更新Java和安卓的方面的知识~ Linux进程通信的知识,建议参照<UNIX环境高级编程>这本书,这里也只是做一个总结: 1.线程:进程中的子线程之间的通信,线程之间的内存(变量)是共享的,通过共享内存也就是全局变量即可,注意互斥即可 2.进程:进程之间的通信必须要借助内核实现: 1)pipe: (无名)管道,只能用于父子进程间通信:单向的(一

Linux编程---进程基础

进程这个概念大家都很熟悉了吧...我就不多说了.. 首先是进程环境.也就是Shell相关的内容. 这都是很基础的我就挑一些我自己都不太清楚的写写. 一.命令行参数 POSIX对命令行的语法约定: 1.实用程序名至少两个,至多9个字符,且只包含小写字母和数字.(Linux应该不止9个吧.我觉得这是Unix下shell的规定). 2.选项名必须是但个字母或者数字,-W选项保留给实现扩展使用,不允许多数字选项. 3.选项和它的选项值可以作为也可以不作为分开的单词.即-ofoo和-o foo是一样的..

Linux:进程通信之消息队列Message实例

/*send.c*/ /*send.c*/ #include <stdio.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #include <errno.h> #define MSGKEY 1024 struct msgstru { long msgtype; char msgtext[2048]; }; main() { struct msgstru ms

Linux下进程通信之管道

每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓冲区,进程2再从内核缓冲区把数据读走,内核提供的这种机制称为进程间通信(IPC,InterProcess Communication).如下图所示. 目前进程通信的方式有: 管道 FIFO 消息队列 信号量 共享内存 套接字 管道 管道概念 管道是Linux支持的最初Unix IPC形式之一,具有以下特点: 管道是半双工的,数

linux编程---进程编程

进程通信(IPC)---信号处理 信号:通过命令kill –l 查看---信号可以由硬件产生,亦可以用软件产生 软件产生信号的函数: kill函数,raise函数,alarm函数,setitimer函数 1:kill函数 功能:系统向进程发起信号:用的多是第一种情况 参数:pid进程号:sig信号 2:raise函数 功能:向本进程发起信号 参数:sig信号 3:alarm函数 功能:过一定时间后向本进程发送SIGALRM信号---缺省操作是结束进程 参数:seconds设置时间的单位是秒  

【Linux】 进程通信--消息队列

一.概念 消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法.  每个数据块都被认为是有一个类型,接收者进程接收的数据块可以有不同的类型值.我们可以通过发送消息 来避免命名管道的同步和阻塞问题.消息队列与管道不同的是,消息队列是基于消息的, 而管道是基于字节流的,且消息队列的读取不?定是先入先出.消息队列与命名管道有一样的不足,就是每个消息的最大长度是有上限的(MSGMAX),每个消息队列的总的字节数是有上限的(MSGMNB),系统上消息队列的总数也有?个上限(MSGMNI). 查看机

linux内核---进程通信---消息队列

转自:https://blog.csdn.net/ljianhui/article/details/10287879 原文地址:https://www.cnblogs.com/qing1991/p/10182521.html

Linux下进程间Socket通信调试debug方法

在一个复杂的软件系统中,往往需要有各个组件之间的数据传递,在组件间数据传递过程中,又会不可避免的出现一些小问题,这时候我们就需要来进行debug了,由于最近的一个系统使用到了collectd和rrdcached来收集数据和画图,它们之间采用了Unix socket通信,因此小小的学习了一下相关知识. 首先我们来回忆下Linux下进程通信有哪些方法: 管道(Pipe)及有名管道(FIFO)\UNIX BSD 信号(Signal) \UNIX BSD 报文消息队列(Message)\UNIX sys