最近学习linux进程通信,发现通信方法太多且具体实现的函数各不相同。最近有些眉目特总结下。由于水平有限,错误之处请大家指出。
管道和有名管道就不用说了,比较好理解。然后还有三种通信方式。分别是:消息队列,信号量(灯?),共享内存。问题就在这。这三种方式又分为两种标准:System V 和POSIX(可能还有别的标准)。而这两种标准的函数又不一样。初学时困扰了我很久。
先说System V消息队列 主要有以下几个函数。
#include <sys/msg.h>
int msgget(ket_t key, int oflag);
int msgsnd(int msgid, const void *ptr, size_t length, int flag);
int msgctl(int msqid, int cmd, struct msqid_ds *buff);
struct msgbuf
{
long int mtype; /* message type, must be > 0 */
char mtext[]; /* message da ta */
};
struct msqid_ds
{
struct ipc_perm msg_perm; /* read-write perms: Section 3.3 */
struct msg *msg_first; /* ptr to first message on queue */
struct msg *msg_last; /* ptr to last message on queue */
msglen_t msg_cbytes; /* current #bytes on queue */
msgqnum_t msg_qnum; /* current #of message on queue */
msglen_t msg_qbytes; /* max #of bytes allowed on queue */
pid_t msg_lspid; /* pid of last msgsnd() */
pid_t msg_lrpid; /* pid of last msgrcv() */
time_t msg_stime; /* time of last msgsnd() */
time_t msg_rtime; /* time of last msgrcv() */
time_t msg_ctime; /* time of last msgctl() */
};
使用时 一个进程用qid=msgget()创建消息队列,返回qid,msgrcv(),msgsed()根据qid就可以读写队列了。
typedef int mqd_t;
mqd_t mq_open(const char *name, int oflag,/* mode_t mode, struct mq_attr *attr */);
int mq_close(mqd_t mqdes);
int mq_unlink(const char *name)
int mq_getattr(mqd_t mqdes, struct mq_attr *attr);
int mq_setattr(mqd_t mqdes, const struct mq_attr *attr, struct mq_attr *attr);
int mq_send(mqd_t mqdes, const char *ptr, size_t len, unsigned int prio);
ssize_t mq_receive(mqd_t mqdes, char *ptr, size_t len, unsigned int *priop);
int mq_notify(mqd_t mqdes, const struct sigevent *notification);
{
long mq_flags; /* message queue flag : 0, O_NONBLOCK */
long mq_maxmsg; /* max number of messages allowed on queue*/
long mq_msgsize; /* max size of a message (in bytes)*/
long mq_curmsgs; /* number of messages currently on queue */
};
#include <sys/mman.h>
int shm_open(const char *name,int oflag,mode_t mode);
int shm_unlink(const char *name);
int ftruncate(int fd,off_t length);
int stat(const char *file_name,struct stat *buf);
mode_t st_mode;
uid_t st_uid;
gid_t st_gid;
off_t st_size;
};
#include <sys/ipc.h>;
#include <sys/sem.h>;
key_t ftok(char *pathname,char proj);
int semget(key_t key,int nsems,int semflg);
int semctl(int semid,int semnum,int cmd,union semun arg);
int semop(int semid,struct sembuf *spos,int nspos);
struct sembuf {
short sem_num; /* 使用那一个信号 */
short sem_op; /* 进行什么操作 */
short sem_flg; /* 操作的标志 */
};
这个么大用过。就抄了点函数。其中ftok()用来产生key。所有System V IPC都用这个汉说生成key。但我测试时都不用ftok()。产生的key都一样但ID不一样,我觉得可以用ID来区分,还望高手指点。
POSIX 信号量
#include<semaphore>
sem_t *sem_open( const char *name,int folag);
sem_t *sem_open( const char *name,int folag,mode_t mode,unsigned int value);
int sem_close(sem_t *sem);
int sem_unlink(const char *name);
int sem_destroy(sem_t *sem);
int sem_init(sem_t *sem, int pshared, unsigned int value);
int sem_wait(sem_t *sem);
int sem_post(sem_t *sem);
int sem_trywait(sem_t *sem);
int sem_getvalue(sem_t *sem, int *sval);
这个比较简单也不写了(主要是吃饭时间到了,下午还有事)。