学习内容:
一、进程间通信方式
1、有名管道(FIFO)和管道(PIPO)。
管道:(1)单向,先进先出,把一个进程的输入和输出连接在一起。
(2)在管道的尾部写入程序,在管道的头部读出数据。
(3)数据被一个进程读取后,将从管道删除。
(4)进程阻塞情况:读空管道时,或者进程已经写满。、
*(无名)管道:父进程和子进程之间的通信 int pipe( int fieldis[2] ) ; 数组保存两个文件描述符
fieldis[0] 用于读管道 fieldis[1] 用于写管道
父进程写程序,子进程读程序:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.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;
}
必须在使用fork()函数之前调用pipe()创建管道,否则子进程不会继承父进程的文件描述符
*有名管道:任意两个进程间的通信
写文件
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
int main()
{
int ret,fd;
char buf[32]={0};
/* ret = mkfifo("fifo.tmp",666);
if(ret == -1)
{
perror("mkfifo");
exit(1);
}*/
fd = open("fifo.tmp",O_WRONLY);
if(-1 == fd)
{
perror("open");
exit(1);
}
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);
return 0;
}
读文件
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
int main()
{
int ret,fd;
char buf[32]={0};
ret = mkfifo("fifo.tmp",666);
if(ret == -1)
{
perror("mkfifo");
exit(1);
}
fd = open("fifo.tmp",O_RDONLY);
if(-1 == fd)
{
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;
}
匹配到bye 则终止
2、信号。
#include <stdio.h>
#include <signal.h>
void print(int num)
{
printf("helloworld! %d \n",num);
}
int main()
{
signal(2,print);
while(1);
return 0;
}
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
void print()
{
alarm(1);
printf("helloworld\n");
}
int main()
{
alarm(1);
signal(SIGALRM,print);
while(1);
return 0;
}
3、消息队列。
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <string.h>
#define MSGKEY 1234
struct msgbuf
{
long mtype;
char mtext[64];
};
int main()
{
int ret;
struct msgbuf mbuf;
int msgid = msgget(MSGKEY, IPC_CREAT | IPC_EXCL);
if(-1 == msgid)
{
perror("msgget");
exit(1);
}
pid_t pid = fork();
if(-1 == pid)
{
perror("fork");
exit(1);
}
else if(0 == pid)
{
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"))
{
mbuf.mtype = 2;
msgsnd(msgid,&mbuf,sizeof(mbuf.mtext),0);
break;
}
}
}
else
{
while(1)
{
memset(&mbuf,0,sizeof(mbuf));
ret = msgrcv(msgid,&mbuf,sizeof(mbuf.mtext),2,0);
if(-1 == ret)
{
perror("msgrcv");
exit(1);
}
if(!strcmp(mbuf.mtext,"bye"))
{
kill(pid,2);
break;
}
printf("\t\t\t\t%s\n",mbuf.mtext);
}
}
sleep(1);
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 1234
struct msgbuf
{
long mtype;
char mtext[64];
};
int main()
{
int ret;
struct msgbuf mbuf;
int msgid = msgget(MSGKEY,0);
if(-1 == msgid)
{
perror("msgget");
exit(1);
}
pid_t pid = fork();
if(-1 == pid)
{
perror("fork");
exit(1);
}
else if(0 == pid)
{
while(1)
{
memset(&mbuf,0, sizeof(mbuf));
mbuf.mtype = 2;
scanf("%s",mbuf.mtext);
ret = msgsnd(msgid,&mbuf,sizeof(mbuf.mtext),0);
if(-1 == ret)
{
perror("msgsnd");
exit(1);
}
if(!strcmp(mbuf.mtext,"bye"))
{
mbuf.mtype = 1;
msgsnd(msgid,&mbuf,sizeof(mbuf.mtext),0);
break;
}
}
}
else
{
while(1)
{
memset(&mbuf,0,sizeof(mbuf));
ret = msgrcv(msgid,&mbuf,sizeof(mbuf.mtext),1,0);
if(-1 == ret)
{
perror("msgrcv");
exit(1);
}
if(!strcmp(mbuf.mtext,"bye"))
{
kill(pid,2);
break;
}
printf("\t\t\t\t%s\n",mbuf.mtext);
}
}
sleep(1);
msgctl(msgid,IPC_RMID,NULL);
return 0;
}
4、共享内存。
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/sem.h>
#define SHMKEY 1234
#define SHMSIZE 4096
#define SEMKEY 1234
union semun {
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO
(Linux specific) */
};
void sem_p(int semid)
{
int ret;
struct sembuf sbuf;
sbuf.sem_num = 0;
sbuf.sem_op = 1;
sbuf.sem_flg = SEM_UNDO;
ret = semop(semid,&sbuf,1);
if(-1 == ret)
{
perror("semop");
return;
}
}
void sem_v(int semid)
{
int ret;
struct sembuf sbuf;
sbuf.sem_num = 0;
sbuf.sem_op = -1;
sbuf.sem_flg = SEM_UNDO;
ret = semop(semid,&sbuf,1);
if(-1 == ret)
{
perror("semop");
return;
}
}
int main()
{
int shmid;
int semid,ret;
int count = 0;
void *shmaddr;
shmid = shmget(SHMKEY,SHMSIZE,IPC_CREAT | IPC_EXCL);
if(-1 == shmid)
{
perror("shmget");
exit(1);
}
semid = semget(SEMKEY, 1 ,IPC_CREAT | IPC_EXCL);
if(-1 == semid)
{
perror("semget");
exit(1);
}
union semun unsem;
unsem.val = 1;
ret = semctl(semid, 0, SETVAL,unsem);
if(-1 == ret)
{
perror("semctl");
exit(1);
}
shmaddr = shmat(shmid,NULL,0); //映射到虚拟地址
if(NULL == shmaddr)
{
perror("shmat");
exit(1);
}
*(int *)shmaddr = count; //数据写到共享内存
while(1)
{
sem_p(semid);
count = *(int *)shmaddr; //读取数据
usleep(100000);
if(count >= 100)
{
break;
}
printf("Process A : count = %d\n",count);
count++;
*(int *)shmaddr = count;
sem_v(semid);
}
shmdt(shmaddr);
shmctl(shmid,IPC_RMID,NULL);
semctl(semid, 0, IPC_RMID);
return 0;
}
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/sem.h>
#define SHMKEY 1234
#define SHMSIZE 4096
#define SEMKEY 1234
union semun {
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO
(Linux specific) */
};
void sem_p(int semid)
{
int ret;
struct sembuf sbuf;
sbuf.sem_num = 0;
sbuf.sem_op = -1;
sbuf.sem_flg = SEM_UNDO;
ret = semop(semid,&sbuf,1);
if(-1 == ret)
{
perror("semop");
return;
}
}
void sem_v(int semid)
{
int ret;
struct sembuf sbuf;
sbuf.sem_num = 0;
sbuf.sem_op = 1;
sbuf.sem_flg = SEM_UNDO;
ret = semop(semid,&sbuf,1);
if(-1 == ret)
{
perror("semop");
return;
}
}
int main()
{
int shmid;
int semid,ret;
int count = 0;
void *shmaddr;
shmid = shmget(SHMKEY,SHMSIZE,0);
if(-1 == shmid)
{
perror("shmget");
exit(1);
}
semid = semget(SEMKEY ,1, 0);
if(-1 == semid)
{
perror("semget");
exit(1);
}
shmaddr = shmat(shmid,NULL,0); //映射到虚拟地址
if(NULL == shmaddr)
{
perror("shmat");
exit(1);
}
while(1)
{
sem_p(semid);
count = *(int *)shmaddr; //读取数据
usleep(100000);
if(count >= 100)
{
break;
}
printf("Process B : count = %d\n",count);
count++;
*(int *)shmaddr = count;
sem_v(semid);
}
shmdt(shmaddr);
return 0;
}