Linux下IPC机制

Linux下IPC机制

实践要求

研究Linux下IPC机制:原理,优缺点,每种机制至少给一个示例,提交研究博客的链接

  • 共享内存
  • 管道
  • FIFO
  • 信号
  • 消息队列

    IPC

    进程间通信(IPC,InterProcess Communication)是指在不同进程之间传播或交换信息。

IPC的方式通常有管道(包括无名管道和命名管道)、消息队列、信号量、共享存储、Socket、Streams等。其中 Socket和Streams支持不同主机上的两个进程IPC。

共享内存

共享内存(Shared Memory)实际就是文件映射的一种特殊情况。进程在创建文件映射对象时用0xFFFFFFFF来代替文件句柄(HANDLE),就表示了对应的文件映射对象是从操作系统页面文件访问内存,其它进程打开该文件映射对象就可以访问该内存块。由于共享内存是用文件映射实现的,所以它也有较好的安全性,也只能运行于同一计算机上的进程之间。

定义

共享内存使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。

实例
#include<stdio.h>
#include<unistd.h>

int main()
{
 int fd[2];  // 两个文件描述符
 pid_t pid;
 char buff[20];

 if(pipe(fd) < 0)  // 创建管道
     printf("Create Pipe Error!\n");

 if((pid = fork()) < 0)  // 创建子进程
    printf("Fork Error!\n");
 else if(pid > 0)  // 父进程
 {
     close(fd[0]); // 关闭读端
     write(fd[1], "hello world\n", 12);
}
 else
 {
     close(fd[1]); // 关闭写端
    read(fd[0], buff, 20);
     printf("%s", buff);
 }

 return 0;
 }

管道

管道,通常指无名管道,是 UNIX 系统IPC最古老的形式。

特点:
  • 它是半双工的(即数据只能在一个方向上流动),具有固定的读端和写端。

  • 它只能用于具有亲缘关系的进程之间的通信(也是父子进程或者兄弟进程之间)。

  • 它可以看成是一种特殊的文件,对于它的读写也可以使用普通的read、write 等函数。但是它不是普通的文件,并不属于其他任何文件系统,并且只存在于内存中。

    实例
    ```` 1 #include<stdio.h>
    2 #include<unistd.h>
    3
    4 int main()
    5 {
    6 int fd[2]; // 两个文件描述符
    7 pid_t pid;
    8 char buff[20];
    9
    10 if(pipe(fd) < 0) // 创建管道
    11 printf("Create Pipe Error!\n");
    12
    13 if((pid = fork()) < 0) // 创建子进程
    14 printf("Fork Error!\n");
    15 else if(pid > 0) // 父进程
    16 {
    17 close(fd[0]); // 关闭读端
    18 write(fd[1], "hello world\n", 12);
    19 }
    20 else
    21 {
    22 close(fd[1]); // 关闭写端
    23 read(fd[0], buff, 20);
    24 printf("%s", buff);
    25 }
    26
    27 return 0;
    28 }
###FIFO
FIFO,也称为命名管道,它是一种文件类型。
####特点

- FIFO可以在无关的进程之间交换数据,与无名管道不同。

- FIFO有路径名与之相关联,它以一种特殊设备文件形式存在于文件系统中。
####实例

1 #include<stdio.h>
2 #include<stdlib.h> // exit
3 #include<fcntl.h> // O_WRONLY
4 #include<sys/stat.h>
5 #include<time.h> // time
6
7 int main()
8 {
9 int fd;
10 int n, i;
11 char buf[1024];
12 time_t tp;
13
14 printf("I am %d process.\n", getpid()); // 说明进程ID
15
16 if((fd = open("fifo1", O_WRONLY)) < 0) // 以写打开一个FIFO
17 {
18 perror("Open FIFO Failed");
19 exit(1);
20 }
21
22 for(i=0; i<10; ++i)
23 {
24 time(&tp); // 取系统当前时间
25 n=sprintf(buf,"Process %d's time is %s",getpid(),ctime(&tp));
26 printf("Send message: %s", buf); // 打印
27 if(write(fd, buf, n+1) < 0) // 写入到FIFO中
28 {
29 perror("Write FIFO Failed");
30 close(fd);
31 exit(1);
32 }
33 sleep(1); // 休眠1秒
34 }
35
36 close(fd); // 关闭FIFO文件
37 return 0;
38 }

###信号
信号是进程间通信机制中唯一的异步通信机制,可以看作是异步通知,通知接收信号的进程有哪些事情发生了。信号机制经过POSIX实时扩展后,功能更加强大,除了基本通知功能外,还可以传递附加信息。
####实例

include <signal.h>

include <sys/types.h>

include <unistd.h>

void new_op(int,siginfo_t,void);
int main(int argc,char**argv)
{
struct sigaction act;
int sig;
sig=atoi(argv[1]);
sigemptyset(&act.sa_mask);
act.sa_flags=SA_SIGINFO;
act.sa_sigaction=new_op;
if(sigaction(sig,&act,NULL) < 0)
{
printf("install sigal error\n");
}
while(1)
{
sleep(2);
printf("wait for the signal\n");
}
}
void new_op(int signum,siginfo_t info,void myact)
{
printf("receive signal %d", signum);
sleep(5);

###消息队列
- 消息队列,是消息的链接表,存放在内核中。一个消息队列由一个标识符(即队列ID)来标识。

- 特点:

消息队列是面向记录的,其中的消息具有特定的格式以及特定的优先级。

消息队列独立于发送与接收进程。进程终止时,消息队列及其内容并不会被删除。

消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取。
####实例

#include <stdio.h>
2 #include <stdlib.h>
3 #include <sys/msg.h>
4
5 // 用于创建一个唯一的key
6 #define MSG_FILE "/etc/passwd"
7
8 // 消息结构
9 struct msg_form {
10 long mtype;
11 char mtext[256];
12 };
13
14 int main()
15 {
16 int msqid;
17 key_t key;
18 struct msg_form msg;
19
20 // 获取key值
21 if((key = ftok(MSG_FILE,'z')) < 0)
22 {
23 perror("ftok error");
24 exit(1);
25 }
26
27 // 打印key值
28 printf("Message Queue - Server key is: %d.\n", key);
29
30 // 创建消息队列
31 if ((msqid = msgget(key, IPC_CREAT|0777)) == -1)
32 {
33 perror("msgget error");
34 exit(1);
35 }
36
37 // 打印消息队列ID及进程ID
38 printf("My msqid is: %d.\n", msqid);
39 printf("My pid is: %d.\n", getpid());
40
41 // 循环读取消息
42 for(;;)
43 {
44 msgrcv(msqid, &msg, 256, 888, 0);// 返回类型为888的第一个消息
45 printf("Server: receive msg.mtext is: %s.\n", msg.mtext);
46 printf("Server: receive msg.mtype is: %d.\n", msg.mtype);
47
48 msg.mtype = 999; // 客户端接收的消息类型
49 sprintf(msg.mtext, "hello, I'm server %d", getpid());
50 msgsnd(msqid, &msg, sizeof(msg.mtext), 0);
51 }
52 return 0;
53 }
复制代码
msg_client.c

复制代码
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <sys/msg.h>
4
5 // 用于创建一个唯一的key
6 #define MSG_FILE "/etc/passwd"
7
8 // 消息结构
9 struct msg_form {
10 long mtype;
11 char mtext[256];
12 };
13
14 int main()
15 {
16 int msqid;
17 key_t key;
18 struct msg_form msg;
19
20 // 获取key值
21 if ((key = ftok(MSG_FILE, 'z')) < 0)
22 {
23 perror("ftok error");
24 exit(1);
25 }
26
27 // 打印key值
28 printf("Message Queue - Client key is: %d.\n", key);
29
30 // 打开消息队列
31 if ((msqid = msgget(key, IPC_CREAT|0777)) == -1)
32 {
33 perror("msgget error");
34 exit(1);
35 }
36
37 // 打印消息队列ID及进程ID
38 printf("My msqid is: %d.\n", msqid);
39 printf("My pid is: %d.\n", getpid());
40
41 // 添加消息,类型为888
42 msg.mtype = 888;
43 sprintf(msg.mtext, "hello, I'm client %d", getpid());
44 msgsnd(msqid, &msg, sizeof(msg.mtext), 0);
45
46 // 读取类型为777的消息
47 msgrcv(msqid, &msg, 256, 999, 0);
48 printf("Client: receive msg.mtext is: %s.\n", msg.mtext);
49 printf("Client: receive msg.mtype is: %d.\n", msg.mtype);
50 return 0;
51 }
````

转载于:https://www.cnblogs.com/l97----/p/7901003.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值