Linux 进程间通信(一)

时间:2023-03-08 22:31:02

Linux 进程间通信

  进程是一个独立的资源分配单位,不同进程之间的资源是相互独立的,没有关联,不能在一个进程中直接访问另一个进程中的资源。但是,进程不是孤立的,不同的进程之间需要信息的交换以及状态的传递,因此需要进程间数据传递、同步与异步的机制。

分类

  • 统一主机间进程通信
    • Unix进程间通信方式
      • 无名通道
      • 有名通道
      • 信号
    • System V进程间通信方式
      • 信号量
      • 消息队列
      • 共享内存
  • 不同主机间进程通信
      • RPC
      • Socket

消息队列IPC

简单介绍下,所有相关的API函数:

API函数 用途
msgget   创建一个新的消息队列       
  获取消息队列ID
msgsnd        向消息队列发送消息
msgrcv 从消息队列接受消息
msgctl 获得消息队列的信息
  设置消息队列的信息
  删除消息队列

函数原型如下:

// 函数原型
#include <sys/msg.h> int msgget( key_t key, int msgflag);
/*
key为消息队列的描述符
msgflag是一个设置选项,可以设置权限 返回值为消息队列ID
*/ int msgctl( int msgid, int cmd, struct msqid_ds *buf);
/*
msgid是msgget的返回值
cmd :IPC_STAT 获取消息队列当前的状态信息,保存到buf指向的空间
IPC_SET 设置消息队列的属性
IPC_RMID 从内核中删除msgid标识的消息队列
*/ int msgsnd( int msgid, struct msgbuf *msgp, size_t msgsz, int msgflag);
/*
msgid为消息队列ID
msgbuf 指向要发送的消息
msgsize 消息的大小
msgflag 操作标志位
*/ int msgrcv(int msgid, struct msgbuf *msgbuf, size_t msgsize, long int msgtype, int msgflag);
/*
msgtype用来指定要接收的消息,分三种情况:
等于 0 返回消息队列中的第一个消息
大于0 返回消息队列中类型为msgtype的第一个消息
小于0 返回消息队列中类型值小于等于msgtype绝对值的消息中类型值最小的第一条消息
*/

例子:

 #include <stdio.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <sys/ipc.h> int main()
{
int msgid; //通过这样可以避免标识符的重复
//key_t myKey;
//myKey = ftok("/home/queues/myqueue", 0); msgid = msgget( 0x111, IPC_CREAT|);
if(msgid >= )
printf("Created a Msg Queue %d\n", msgid); return ;
} 创建消息队列

创建消息队列

 #include <stdio.h>
#include <sys/msg.h>
#include <sys/types.h> int main(int argc, char **argv)
{
int msgid, ret;
struct msqid_ds buf; //获取消息队列
msgid = msgget(0x111, ); if(msgid >= ){
ret = msgctl(msgid, IPC_STAT, &buf);
buf.msg_qbytes = ; ret = msgctl(msgid, IPC_SET, &buf); if(ret == ){
printf("change queue size success");
}
} return ;
}

配置消息队列

 #include <stdio.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <string.h> typedef struct{
long type;
float fval;
unsigned int unival;
char message[];
}myType; int main()
{
myType msg;
int qid,ret; qid = msgget(0x111, );
if(qid > ){
msg.type = 1L;
msg.fval = 123.456;
msg.unival = ;
strcpy( msg.message, "this is a msg in queue\n"); ret = msgsnd(qid, (struct msgbuf*)&msg, sizeof(myType), );
if(ret != -)
printf("sent success!\n");
} return ;
}

向消息队列发送消息

 #include <stdio.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <string.h> typedef struct{
long type;
float fval;
unsigned int unival;
char message[];
}myType; int main()
{
myType msg;
int qid,ret; qid = msgget(0x111, );
if(qid >= ){ ret = msgsnd(qid, (struct msgbuf*)&msg, sizeof(myType), );
if(ret != -)
printf("recv success!\n");
printf("type : %ld\n", msg.type);
printf("float value: %f\n", msg.fval);
printf("Unit value: %d\n", msg.unival);
printf("String value: %s\n", msg.message);
} return ;
}

从消息队列读取消息

共享内存

  使用消息队列时,一个进程要向队列中写入消息,这要引起从用户地址空间的一次复制,当另外一个进程要从消息队列中读取消息时,又要进行一次从内核空间向用户空间的一次复制。而共享内存的优点就是完全省去了这些复制操作。

  简单介绍下API函数:

API函数 用途                                                                                             
shmget             创建一个新的共享内存区段
  取得一个已经创建的共享内存区段的描述符
shmctl 取得一个共享内存区段的信息
  为一个共享内存区段设置特定的信息
  删除一个共享内存区段
shmat 挂接一个共享内存区段
shmdt 与一个共享内存区段分离

  函数原型如下:

//函数原型
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h> int shmget( key_t key, size_t size, int shmflag );
/*
key为描述符
size为共享内存区段的大小
shmflag为指令和权限设置
*/ int shmctl( int shmid, int cmd, struct shmid_ds *buf );
/*
shmid指共享内存ID
cmd为指令
*/ void *shmat( int shmid, const void *shmaddr, int shmflag);
/*
shmaddr指定共享内存出现在进程内存地址的什么位置,直接指定为NULL让内核自己决定一个合适的地址位置
shmflg SHM_RDONLY:为只读模式,其他为读写模式
*/ int shmdt( const void *shmaddr );

例子:

 #include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h> int main()
{
int shmid; shmid = shmget( 0x123, , IPC_CREAT|);
if(shmid >= )
printf("Created a shared memory %d\n", shmid); return ;
}

创建共享内存

 #include <stdio.h>
#include <sys/shm.h>
#include <errno.h>
#include <sys/ipc.h>
#include <sys/types.h> int main(int argc, char **argv)
{
int shmid, ret;
struct shmid_ds shmds; //获取共享内存
shmid = shmget(0x123, , ); if(shmid >= ){
ret = shmctl(shmid, IPC_STAT, &shmds);
if(ret == ){
printf("shared memory size : %d/n", shmds.shm_segsz);
printf("attaches number: %d/n", (int)shmds.shm_nattch);
}else
printf("shmctl error!\n");
}else
printf("shared memory not found!\n"); return ;
}

取得共享内存

 #include <stdio.h>
#include <sys/shm.h>
#include <errno.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <string.h> int main(int argc, char **argv)
{
int shmid, ret;
void* mem; //获取共享内存
shmid = shmget(0x123, , ); if(shmid >= ){ mem = shmat( shmid, (const void*), ); strcpy((char*)mem, "This is a shared memory\n"); ret = shmdt(mem); }else
printf("shared memory not found!\n"); return ;
}

写入共享内存

 #include <stdio.h>
#include <sys/shm.h>
#include <errno.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <string.h> int main(int argc, char **argv)
{
int shmid, ret;
void* mem; //获取共享内存
shmid = shmget(0x123, , ); if(shmid >= ){ mem = shmat( shmid, (const void*), ); printf("%s", (char*)mem); ret = shmdt(mem); }else
printf("shared memory not found!\n"); return ;
}

读取共享内存

 #include <stdio.h>
#include <sys/shm.h>
#include <errno.h>
#include <sys/ipc.h>
#include <sys/types.h> int main(int argc, char **argv)
{
int shmid, ret; //获取共享内存
shmid = shmget(0x123, , ); if(shmid >= ){
ret = shmctl(shmid, IPC_RMID, );
if(ret == ){
printf("shared memory removed!");
}else
printf("shmctl error!\n");
}else
printf("shared memory not found!\n"); return ;
}

删除共享内存

参考

GNU/Linux环境编程

http://blog.sina.com.cn/s/blog_7f98bac10100s91d.html

http://www.cnblogs.com/joeblackzqq/archive/2011/05/31/2065161.html

Linux 进程间通信(一)
Linux 进程间通信 由 cococo点点 创作,采用 知识共享 署名-非商业性使用-相同方式共享 3.0 * 许可协议进行许可。欢迎转载,请注明出处:转载自:cococo点点 http://www.cnblogs.com/coder2012