linux进程间通信实质就是I/O操作
通信方式:
1管道
2信号
3共享内存
4消息队列
5信号量
6基于套接字(socket)的进程通信
无名管道:
例子:
①建立一个管道
②父进程写入一些内容
③子进程读取一些内容,并且打印出来
思路:
① pipe()建立管道
②fork()生产新进程
③判断,如果是父,则写入管道内容fd(1)
④判断,如果是子,则读出管道内容fd(0)
⑤关闭文件描述符
1 #include<unistd.h>
2 #include<stdio.h>
3 #include<stdlib.h>
4 #include<string.h>
5 int main()
6 {
7 int pfd[2];
8 pid_t pid;
9 char w_cont[] = "hello";
10 char r_cont[255];
11 //creat pipe
12 if(pipe(pfd) < 0)
13 {
14 //failed
15 perror("creat pipe failed");
16 return -1;
17 }else{
18 if((pid = fork()) < 0){
19
20 perror("creat process failed");
21 }else if(pid > 0){
22 //parent process
23 close(pfd[0]);
24 write(pfd[1],w_cont,strlen(w_cont));
25 close(pfd[1]);
26
27 }else{
28 //child process
29
30 close(pfd[1]);
31 read(pfd[0],r_cont,255);
32 printf("child process read:%s\n",r_cont);
33 }
34 }
35 return 0;
36 }
程序有点问题,输出有乱码 原因为没有结束标志
有名管道
函数原型
int mkfilo(const char *pathname,mode_t mode)
编码操作
建立有名管道文件让两个进程操作这个文件 open write read
例子
1建立一个fifo_r 用来读取有名管道
2建立一个fifo_w用来写入有名管道
3两个进程通过有名管道通信
#include<sys/types.h>
#include<sys/stat.h>
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
#include<errno.h>
#define FIFO_PATH "myfifofile"
// read file
int main()
{
int fd;
char cont_r[255];
//create fifo file
if(mkfifo(FIFO_PATH,0666) < 0 && errno != EEXIST )
{
perror("create fifo failed");
return -1;
}else
{
printf("create fifo success\n");
//open fifo file
fd = open(FIFO_PATH,O_CREAT|O_RDONLY,0666);
if(fd>0)
{
//read content
while(1)
{
read(fd,cont_r,255);
printf("read:%s\n",cont_r);
}
}else
perror("open failed");
return 0;
}
}
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
#include<fcntl.h>
#include<errno.h>
#include <unistd.h>
#define FIFO_PATH "myfifofile"
// writ file
int main()
{
int fd;
char cont_w[] = "hello my sun !";
//create fifo file
if(mkfifo(FIFO_PATH,0666) < 0 && errno != EEXIST)
{
perror("create fifo failed");
return -1;
}else
{
printf("create fifo success\n");
//open fifo file
fd = open(FIFO_PATH,O_CREAT|O_WRONLY,0666);
if(fd > 0)
{
//read content
while(1)
{
write(fd,cont_w,strlen(cont_w));
printf("write success\n");
sleep(2);
}
}else
perror("open failed");
return 0;
}
}
信号
即为软中断信号,用来通知进程发生了异步事件
进程处理信号的方式:
1忽略此信号(SIGKILL SIGSTOP 不能被忽略)
2执行用户希望的动作
3执行系统默认的动作
常用的信号
向进程本身发送信号 int raise(int SIGNO)
#inxlude<signal.h>
#include<stdio.h>
int main()
{
pid_t pid;
if((pid = fork()) < 0)
printf("error");
}else if(pid == 0)
{
}else
{
while(1)
{
pid++;
}
}
return 0;
}
向指定进程发送信号
int kill(pid_t pid ,int SIGNO)
#include<signal.h>
#include<stdio.h>
#include<sys/types.h>
int main()
{
//kill process 3031
kill(3031,SIGKILL);
printf("process 3031 was killed\n");
return 0;
}
特殊发送信号函数
unsigned int alarm(unsigred int seconds)
默认信号是退出
#include<unistd.h>
#include<stdio.h>
int main()
{
int a;
alarm(2);
while(1)
{
a++;
}
printf("exit\n");
return 0;
}
等待信号 pause()
简单的信号处理
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
函数指针 一个函数的首地址
指针函数 返回值是指针的函数
#include<signal.h>
#include<unistd.h>
#include<stdio.h>
void sig_handler(int sig_no)
{
if(sig_no == SIGINT)
{
printf("get SIGINT\n");
}else if(sig_no == SIGQUIT)
{
printf("get SIGQUIT\n");
}
}
int main()
{
printf("waiting for signal\n");
//register signal
signal(SIGINT,sig_handler);
signal(SIGQUIT,sig_handler);
pause();
return 0;
}
输出结果
book@book-desktop:~/wanglei$ gcc -o sendsignal sendsignal.c
book@book-desktop:~/wanglei$ ./sendsignal
waiting for signal
^Cget SIGINT
book@book-desktop:~/wanglei$ ./sendsignal
waiting for signal
^\get SIGQUIT
内核代码 发送信号 注册信号 处理信号
共享内存
内存:虚拟内存4G
进程间通信查看命令ipcs
例子:建立两个进程,一个写一个读
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/types.h>
#include<string.h>
#include<stdio.h>
int main()
{
char contents[] = "hello sundy";
void *share_memory = (void *)0;
//1 create share memory
int shmid = shmget(123345,2048,IPC_CREAT|0666);
if(shmid != -1)
{
//2map address
share_memory = shmat(shmid,NULL,0);
if(share_memory != (void *)-1)
{
//copy men
memcpy(share_memory,contents,12);
printf("save successed\n");
shmdt(share_memory);
}
}
return 0;
}
#include<sys/ipc.h>
2 #include<sys/shm.h>
3 #include<sys/types.h>
4 #include<string.h>
5 #include<stdio.h>
6 int main()
7 {
8 char contents[] = "hello sundy";
9 void *share_memory = (void *)0;
10 //1 create share memory
11 int shmid = shmget(233465,2048,IPC_CREAT|0666);
12 if(shmid != -1)
13 {
14 //2map address
15 share_memory = shmat(shmid,NULL,0);
16 if(share_memory != (void *)-1)
17 {
18 //copy men
19 //memcpy(share_memory,contents,12);
20 printf("get share memory value:%s\n",share_memory);
21 shmdt(share_memory);
22 }
23 }
24 return 0;
25 }
消息队列
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<stdio.h>
#include<string.h>
struct msgbuf
{
long mtype;
char mtext[255];
};
int main()
{ struct msgbuf mybuf;
mybuf.mtype = 1;
strcpy(mybuf.mtext,"hello sundy");
//creat message queue
int msgqid = msgget(2345,IPC_CREAT|0666);
if(msgqid != -1)
{
//2send message
if(msgsnd(msgqid,&mybuf,sizeof(mybuf.mtext),0) != -1)
{
printf("send message success\n");
}else
perror("msgsnd error");
}else
perror("msgget error");
return 0;
}
#include<sys/types.h>
2 #include<sys/ipc.h>
3 #include<sys/msg.h>
4 #include<stdio.h>
5 #include<string.h>
6 struct msgbuf
7 {
8 long mtype;
9 char mtext[255];
10 };
11 int main()
12 { struct msgbuf mybuf;
13 //mybuf.mtype = 1;
14 //strcpy(mybuf.mtext,"hello sundy");
15 //creat message queue
16 int msgqid = msgget(2345,IPC_CREAT|0666);
17 if(msgqid != -1)
18 {
19 //2recive message
20 // IPC_NOWAIT if(msgrcv(msgqid,&mybuf,sizeof(mybuf.mtext),0,0) != -1)
21 {
22 printf("recrive message:%s\n",mybuf.mtext);
//deletc queue
if(msgctl(msgqid,IPC_RMID,0) != -1)
printf("deletc queue success\n");
23 }else
24 perror("msgsnd error");
25 }else
26 perror("msgget error");
27 return 0;
28 }
信号量