进程间通信(IPC)方式
管道:有名管道和无名管道
消息队列
信号量
共享内存
套接字
进程间通信的目的:
1、数据传输:
2、共享数据:多个进程想要操作共享数据,一个进程对共享数据的修改,别的进程一个第一时间看到
3、通知事件:一个进程需要向另一个或一组进程发送消息,通知他们发生了某种事件(如进程终止时通知父进程)
4、资源共享:多个进程之间共享同样的资源,未做到这一点,需要内核提供锁和同步机制。
5、进程控制
管道通信:无名管道:一端写,一端读
管道是半双工的,数据只能向一个方向流动
必须在系统调用fork()前调用pipe(),否则子进程将不会继承文件描述符
1如果管道的写端不存在,则认为已经读到数据末尾,改函数返回的读出字节数为0;
2如果写端存在时,如果请求的字节数目大于PIPE_BUF,则返回现有的管道数据字节数;如果不大于,则返回现有数据字节数,或请求字节数。
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<stdlib.h>
#include<string.h>
#include<sys/wait.h>
int main()
{
int status;
int fd[2];
pid_t pid;
if(-1==pipe(fd))
{
perror("error");
exit(1);
}
pid = vfork();
if(-1 == pid)
{
perror("fork error");
exit(1);
}
if(0 == pid)
{
char buff[20]={0};
printf("child\n");
printf("please input:\n");
scanf("%s",buff);
write(fd[1],buff,strlen(buff));
exit(0);
}
else
{
waitpid(pid,&status,0);
char buffer[1024]={0};
read(fd[0],buffer,20);
printf("%s\n",buffer);
printf("father\n");
}
}
mode:O_WRONLY
O_RDONLY
有名管道 进程间相互输入输出
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/wait.h>
#include<sys/types.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/stat.h>
#define FIFO "./test.txt"
int main()
{
int i=0;
pid_t pid;
int info=mkfifo(FIFO,0666);
int status;
int fd;
if(info<0)
{
perror("mkfifo error");
exit(1);
}
pid = fork();
if(-1 == pid)
{
perror("error\n");
exit(1);
}
if(0 == pid)
{
while(1)
{
fd = open(FIFO,O_WRONLY);
char buf[25]={0};
printf("child input1:\n");
scanf("%s",buf);
write(fd,buf,strlen(buf));
memset(buf,0,sizeof(buf));
sleep(1);
fd = open(FIFO,O_RDONLY);
read(fd,buf,20);
printf("child speak to father: %s\n",buf);
memset(buf,0,sizeof(buf));
}
exit(0);
}
else
{
while(1)
{
fd = open(FIFO,O_RDONLY);
char buffer[1024]={0};
read(fd,buffer,12);
printf("father speak to child: %s\n",buffer);
memset(buffer,0,sizeof(buffer));
fd = open(FIFO,O_WRONLY);
printf("fahter input2:\n");
scanf("%s",buffer);
write(fd,buffer,strlen(buffer));
memset(buffer,0,sizeof(buffer));
sleep(1);
}
}
return 0;
}
进程间通信
write.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/wait.h>
#include<sys/types.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<errno.h>
#define FIFO "./test.txt"
int main()
{
pid_t pid;
char buffer[100];
int ret;
if((ret=mkfifo(FIFO,0644))<0)
{
if(ret==-1&&errno == EEXIST)
{
}
else
{
perror("make mkfifo error");
exit(1);
}
}
int fd=open(FIFO,O_WRONLY);
while(1)
{
memset(buffer,0,sizeof(buffer));
scanf("%s",buffer);
write(fd,buffer,strlen(buffer));
}
return 0;
}
read.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/wait.h>
#include<sys/types.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<errno.h>
#define FIFO "./test.txt"
int main()
{
pid_t pid;
int ret;
char buffer[100];
if((ret=mkfifo(FIFO,0644))<0)
{
if(ret == -1 && errno == EEXIST)
{
}
else
{
perror("error");
exit(0);
}
}
int fd = open(FIFO,O_RDONLY);
while(1)
{
memset(buffer,0,sizeof(buffer));
read(fd,buffer,sizeof(buffer));
printf("recv :%s\n",buffer);
sleep(2);
}
return 0;
}
2.信号:软中断(程序传输信息的媒介)
Ctrl+z:暂停信息
Ctrl+c:停止信号
Int kill(pid_t, int sig)
信号处理
sighandler_t signal(int signum, sighandler_t handler);
信号的编号 信号的处理机制
SIG_IGN:忽略信号
SIG_DFL:信号的直接处理
管道特点:
1传输数据量少,因此只适合小数据的传输
2 管道数据被读出时会自动删除
3 管道数据是以什么格式输出:结构化,非结构化和半结构化。
共享内存
无格式:
当数据量大且读写效率要求较高的时候(读写效率提高减少了进出内核的次数)
内核的实现原理:
在内存中开辟一块内存可以让多个进程共享(malloc)。
如果一个进程对于共享内存的内容进行了更改,其他进程都会受到影响。
一个共享内存的最大容量:shnmax。
Posix:POSIX表示可移植操作系统接口
系统V :
Mmap:mmap将一个文件或者其它对象映射进内存。文件被映射到多个页上,如果文件的大小不是所有页的大小之和,最后一个页不被使用的空间将会清零。mmap在用户空间映射调用系统中作用很大。
开辟共享内存
int shmget(key_t key, size_t size, int shmflg);
共享内存键值:0
IPC_PRIVATE:共享内存的表示符
shmflg:IPC_CREAT
映射共享内存:shmat :
void *shmat(int shmid, const void *shmaddr, int shmflg);
(决定以什么方式来决定映射地址,通常为0)
Eg
#include<stdio.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<unistd.h>
#include<stdlib.h>
struct data
{
char dat[100];
};
int main()
{
struct data *ptr;
int shmid = shmget(1,sizeof(struct data),0666|IPC_CREAT);
int status;
if(-1 == shmid)
{
perror("shmget error");
exit(0);
}
if(ptr==(void *)-1)
{
perror("shmat error");
exit(1);
}
scanf("%s",ptr->dat);
pid_t pid=vfork();
if(-1 == pid)
{
perror("error");
exit(0);
}
if(0==pid)
{
printf("child :%s\n",ptr->dat);
scanf("%s",ptr->dat);
exit(6);
}
else
{
pid = wait(&status);
printf("father %s\n",ptr->dat);
}
int shm = shmctl(shmid,IPC_RMID,NULL);
if(-1==shm)
{
perror("shmtcl error");
exit(2);
}
return 0;
}
共享内存的步骤:1进程调用shmget函数创建新的或获取已有的共享内存
2调用shmat函数将物理内存映射到自己的进程空间
3调用shmdt函数取消映射
4调用shmtl函数释放开辟的物理空间;
使用联合体判断cpu 大端小端
#include "stdio.h"
union w
{
int a; //4 bytes
char b; //1 byte
}c;
int main()
{
c.a=1;
if (c.b==1)
printf("It is Little_endian!/n");
else
printf("It is Big_endian!/n");
return 1;
}