进程间通信现的原因:让不同的进成之间实现数据的交互:
1、进程间通信的发展
管道:内核中分配一块内存空间,第一个进程可以向这个内存空间中装数据,另外一个进程可以向内存空间中取数据。
system V:一类操作系统的名称,这类操作系统为不同的目的设计了不同的大小(消息队列、共享内存和信号量)
POSIX:可移植性操作系统的接口,可以按照这个标准写的接口函数,放到任意操作系统上都可以使用,除了windows操作系统(Windows操作系统没有加入这个组织)。
一.管道的应用
1. 匿名管道
(1) 代码
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
intmain(void)
{
int fds[2];
char buf[100];
int len;
if(pipe(fds)==-1)
perror("make pipe"),exit(1);
while(fgets(buf,100,stdin)){
len=strlen(buf);
//write into pipe
if(write(fds[1],buf,len)!=len){
perror("write to pipe");
break;
}
memset(buf,0x00,sizeof(buf));
//read from pipe
if((len=read(fds[0],buf,100))==-1){
perror("read from pipe");
break;
}
//write to stdout
if(write(1,buf,len)!=len){
perror("write to stdout");
break;
}
}
}
(2) 结果截图
B:
# include<stdio.h>
# include<stdlib.h>
# include<unistd.h>
int main(void)
{
int fds[2];
//调用pipe函数创建管道:分配管道
if(pipe(fds)==-1){
perror("pipe"),exit(1);
}
if(fork()==0){
close(fds[0]);
sleep(2);
write(fds[1],"haha\n",4);
close(fds[1]);
exit(0);
}else{
close(fds[1]);
char buf[100]={};
printf("before read\n");
read(fds[0],buf,100);
printf("after read\n");
close(fds[1]);
printf("%s\n",buf);
exit(0);
}
}
死锁:子进程等待父进程退出,父进程等待子进程退出
# include<stdio.h>
# include<stdlib.h>
# include<unistd.h>
int main(void)
{
int fds[2];
//调用pipe函数创建管道:分配管道
if(pipe(fds)==-1){
perror("pipe"),exit(1);
}
if(fork()>0){
wait(NULL);
close(fds[0]);
// sleep(2);
write(fds[1],"haha\n",4);
close(fds[1]);
exit(0);
}else{
close(fds[1]);
char buf[100]={};
printf("before read\n");
read(fds[0],buf,100);
printf("after read\n");
close(fds[0]);
printf("%s\n",buf);
exit(0);
}
}
2. 用fork共享管道
(1) 代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<unistd.h>
# defineERR_EXIT(m)\
do\
{\
perror(m);\
exit(EXIT_FAILURE);\
}while(0);
intmain(int argc,char *argv[])
{
int pipefd[2];
if(pipe(pipefd)==-1)
ERR_EXIT("pipe error");
pid_t pid;
pid=fork();
if(pid==-1)
perror("fork error");
if(pid==0){
close(pipefd[0]);
write(pipefd[1],"hello",5);
close(pipefd[1]);
exit(EXIT_SUCCESS);
}
close(pipefd[1]);
char buf[10]={0};
read(pipefd[0],buf,10);
printf("buf=%s\n",buf);
return 0;
}
(2) 截图
二.命名管道
1. 用命名管道实现文件拷贝
(1) 读取文件,写入命名管道
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<errno.h>
# defineERR_EXIT(m)\
do\
{\
perror(m);\
exit(EXIT_FAILURE);\
}while(0);
intmain(int argc,char *argv[])
{
int outfd;
outfd=open("abc.bak",O_WRONLY|O_CREAT|O_TRUNC,0644);
if(outfd==-1)
ERR_EXIT("open");
char buf[1024];
int n;
while((n=read(infd,buf,1024))>0)
{
write(outfd,buf,n);
}
close(infd);
close(outfd);
unlink("tp");
return 0;
}
(2) 读取管道,写入目标文件
# include<stdio.h>
# include<stdlib.h>
# include<string.h>
# include<unistd.h>
# include<errno.h>
# define ERR_EXIT(m)\
do\
{\
perror(m);\
exit(EXIT_FAILURE);\
}while(0);
int main(int argc,char *argv[])
{
mkfifo("tp",0644);
int infd;
infd=open("abc",O_EDONLY);
if(infd==-1)
ERR_EXIT("open");
int outfd;
outfd=open("tp",O_WRONLY);
if(outfd==-1)
ERR_EXIT("open");
char buf[1024];
int n;
while((n=read(infd,buf,1024))>0)
{
write(outfd,buf,n);
}
close(infd);
close(outfd);
return 0;
}
.2.用命名管道实现server&client通信
(1) Server
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<stdlib.h>
# defineERR_EXIT(m)\
de{\
perror(m);\
exit(EXIT_FAILURE);\
}while(0);
int main()
{
umask(0);
if(mkfifo("mypipe",0644)<0){
ERR_EXIT("mkfifo");
}
int rfd=open("mypipe",O_RDONLY);
if(rfd<0){
ERR_EXIT("open");
}
char buf[1024];
while(1){
buf[0]=0;
printf("please wit...\n");
ssize_t s=read(rfd,buf,sizeof(buf)-1);
if(s>0){
buf[s-1]=0;
printf("client say#%s\n",buf);
}else if(s==0){
printf("client quit,exitnow!\n");
exit(EXIT_SUCCESS);
}else{
ERR_EXIT("read");
}
}
close(rfd);
retu
(2) client
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
# defineERR_EXIT(m)\
de{\
perror(m);\
exit(EXIT_FAILURE);\
}while(0);