****************进程间通信*******************
#目的
1.数据传输
2.资源共享
3.通知事件
4.进程控制
#发展
1.UNIX进程间通信
2.基于System V进程间通信(常用)
3.POSIX进程间通信(最新)
#POSIX表示可移植操作系统接口
#分类
1.管道(pipe)和有名管道(FIFO)
2.信号(signal)
3.消息队列
4.共享内存
5.信号量
6.套接字(socket)
#管道通信
管道时单向的、先进先出。
一个进程再管道的尾部写入数据
另一个进程从管道的头部读出数据
数据被一个进程读出后,将被从管道中删除
进程试图读空管道时,进程将阻塞。
1.无名管道
用于父进程和子进程间的通信
2.有名管道
后者可用于运行于同一系统中的任意两个进程间的通信
#无名管道创建
int pipe(int filedis[2])
filedis[0]用于读管道
filedis[1]用于写管道
/*************************************************************************
> File Name: pipe.c
> Author: ma6174
> Mail: ma6174@163.com
> Created Time: 2018年08月17日 星期五 09时30分08秒
************************************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<string.h>
#include<sys/wait.h>
void ReadData(int fd)
{
int ret;
char buf[32] = {0};
while(1)
{
ret = read(fd, buf, sizeof(buf));
if( -1 == ret )
{
perror("read");
exit(1);
}
if( !strcmp(buf,"bye"))
{
break;
}
printf("read from pipe:%s\n",buf);
memset(buf, 0, sizeof(buf));
}
close(fd);
}
void WriteData(int fd)
{
int ret;
char buf[32] = {0};
while(1)
{
scanf("%s",buf);
ret = write(fd, buf, strlen(buf));
if( -1 == ret )
{
perror("write");
exit(1);
}
if( !strcmp(buf,"bye"))
{
break;
}
memset(buf, 0 ,sizeof(buf));
}
close(fd);
}
int main()
{
int ret, fd[2] = {0};
pid_t pid;
ret = pipe( fd );
if(-1 == ret )
{
perror("pipe");
exit(1);
}
pid = fork();
if( -1 == pid )
{
perror("fork");
exit(1);
}
else if( 0 == pid )
{
close(fd[1]);
ReadData(fd[0]);
}
else
{
close(fd[0]);
int status;
WriteData(fd[1]);
wait(&status);
}
return 0;
}
#有名管道的创建:
注意:管道名称为:“fifo.tmp”,此项操作关系到内核,所以需要在home目录或根目录下操作。
创建用于写的文件:
#include<stdio.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<fcntl.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
int main()
{
int ret;
int fd;
char buf[64]={0};
fd = open("fifo.tmp", O_WRONLY );
if( -1 == ret )
{
perror("open");
exit(1)
}
while(1)
{
scanf("%s",buf);
ret = write(fd, buf, strlen(buf));
if( -1 == ret )
{
perror("read");
exit(1);
}
if( !strcmp(buf, "bye") )
{
break;
}
memset(buf, 0, sizeof(buf));
}
close(fd);
return 0;
}
创建用于读的文件:
#include<stdio.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<fcntl.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
int main()
{
int ret;
int fd;
char buf[64] = {0};
ret = mkfifo("fifo.tmp",666);
if( -1 == ret )
{
perror("mkfifo");
exit(1);
}
fd = open("fifo.tmp", O_RDONLY );
if( -1 == ret )
{
perror("open");
exit(1);
}
while(1)
{
ret = read(fd, buf, sizeof(buf));
if( -1 == ret )
{
perror("read");
exit(1);
}
if( !strcmp(buf, "bye") )
{
break;
}
printf("%s\n",buf);
memset(buf, 0, sizeof(buf));
}
close(fd);
unlink("fifo.tmp");
return 0;
}
#信号通信
信号机制是Unix系统中最为古老的进程间通信机制,很多条件可以产生一个信号:
1.当用户按某些按键时,产生信号
2.硬件异常产生信号
#alarm(闹钟):
int alarm( int seconds)
#include<stdio.h>
#include<unistd.h>
#include<signal.h>
void print()
{
alarm(1);
printf("hello\n");
}
int main()
{
alarm(1);
signal( SIGALRM, print );
while(1);
return 0;
}
#消息队列
创建消息队列(msgget)
进程A用来发送数据(msgsnd)
进程B用来接收数据(msgrcv)
创建用于发送的消息队列:
注意:由于share文件夹里的权限不够,此项操作关系到内核,所以只能在根目录或home目录里操作。
#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<stdlib.h>
#include<string.h>
#define MSGKEY 2048
struct msgbuf
{
long mtype; /* message type, must be > 0 */
char mtext[64]; /* message data */
};
int main()
{
struct msgbuf mbuf;
int ret;
int msgid;
msgid = msgget( MSGKEY,IPC_CREAT | IPC_EXCL );
if( -1 == msgid )
{
perror("msgget");
exit(1);
}
while(1)
{
memset(&mbuf, 0, sizeof(mbuf));
mbuf.mtype = 1;
scanf("%s",mbuf.mtext);
ret = msgsnd( msgid, &mbuf, sizeof(mbuf.mtext), 0 );
if( -1 == ret )
{
perror("msgsnd");
exit(1);
}
if( !strcmp(mbuf.mtext,"bye") )
{
break;
}
}
msgctl(msgid, IPC_RMID, NULL);
return 0;
}
创建用于接受的消息队列:
#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<stdlib.h>
#include<string.h>
#define MSGKEY 2048
struct msgbuf
{
long mtype; /* message type, must be > 0 */
char mtext[64]; /* message data */
};
int main()
{
struct msgbuf mbuf;
int ret;
int msgid;
msgid = msgget( MSGKEY, 0 );
if( -1 == msgid )
{
perror("msgget");
exit(1);
}
while(1)
{
memset(&mbuf, 0, sizeof(mbuf));
mbuf.mtype = 1;
ret = msgrcv( msgid, &mbuf, sizeof(mbuf.mtext), 1, 0 );
if( -1 == ret )
{
perror("msgsnd");
exit(1);
}
if( !strcmp(mbuf.mtext,"bye") )
{
break;
}
printf("%s\n",mbuf.mtext);
}
msgctl(msgid, IPC_RMID, NULL);
return 0;
}