进程间通信方式通常有共享内存 信号量 消息队列 管道 FIFO Socket等几种。
共享内存(分配 绑定 脱离 释放)
1:效率高,特别是大数据量通信
2:各进程需要协调共同的键值,需要提供额外机制防止竞争条件
3:异步通信
4:和信号量一同使用
内存映射(多进程共享文件进行通信的机制)
1:分配内存
2:读入文件内容至内存
3:内存的内容回写到文件
信号量
1:线程信号量:同步多线程环境的计数器。
2:进程间同步的信号量: System V信号量,操作和sharedmemory类似。
消息队列
1打开或创建消息队列
2读写操作
3获得或设置队列属性
管道
1:单向信息的传递设备
2:用于进程的线程之间或者是父子进程之间通信
3:自动同步进程(管道的容量是有限的当管道写满的时候,写入端自动阻塞管道容量4096字节)
FIFO
1:在文件系统中是一个有名字的管道
2:任何进程都可以打开
3:进程间无需关联
SocketSocket
1:是一种双向通信设备
2:同一主机不同进程间通信
3:不同主机间的通信
以下是一些程序,帮助大家理解
共享内存
#include"stdio.h"
#include"sys/shm.h"
#include"string.h"
#include"fcntl.h"
#include"sys/stat.h"
int main()
{
pid_t pid;
int share_id;
share_id=shmget(IPC_PRIVATE,getpagesize(),IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR );
pid=fork();
if(pid==0)
{
char *share1=NULL;
share1=(char*) shmat (share_id, 0,0);
memset(share1,0,getpagesize());
strcpy(share1,"hello,everyone ");
shmdt(share1);
}
else if(pid>0)
{
char *share2=NULL;
share2=(char*) shmat(share_id,0,0);
printf("read characters from memory! ");
printf("%s ",share2);
shmdt(share2);
shmctl(share_id,IPC_RMID,0);
}
return 1;
}
信号量
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include<stdio.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#define MAX 3
union semun
{
int val;
struct semid_ds *buf;
unsigned short int *array;
struct seminfo *_buf;
};
int sig_alloc(key_t key, int sem_flags)
{
return semget (key, MAX, sem_flags);
}
int sig_destory (int semid,int numth)
{
union semun ignored_argument;
return semctl (semid, numth, IPC_RMID,ignored_argument);
}
/*
parray is a set of initialized value
*/
int sig_init (int semid,int *parray)
{
union semun argument;
int i=0;
for(i=0;i<MAX;i++)
{
// values[i] = *(parray+i);
argument.array = parray;
semctl (semid, i, SETALL, argument);
}
}
int sig_wait(int semid,int numth)
{
struct sembuf operations[MAX];
operations[numth-1].sem_num = numth-1;
operations[numth-1].sem_op = -1;
operations[numth-1].sem_flg = SEM_UNDO;
return semop(semid,operations,1);
}
int sig_post(int semid,int numth)
{
struct sembuf operations[MAX];
operations[numth-1].sem_num = numth-1;
operations[numth-1].sem_op = 1;
operations[numth-1].sem_flg = SEM_UNDO;
return semop(semid,operations,1);
}
int main()
{
pid_t pid;
int sig_id,i=0;
int sig_val[MAX]={1,0,0};
sig_id=sig_alloc(0,IPC_CREAT);
sig_init(sig_id,sig_val);
pid=fork();
if(pid==0)
{
while(++i<10)
{
sig_wait(sig_id,3);
printf("*************** ");
sig_post(sig_id,3);
}
}
else if(pid)
{
i=0;
while(++i<10)
{
sig_wait(sig_id,1);
printf("++++++++++++++++ ");
sig_post(sig_id,1);
}
}
return 1;
}
内存映射
#include <sys/mman.h>
#include <sys/types.h>
#include<stdio.h>
#include<string.h>
#include<sys/stat.h>
#include<stdlib.h>
#include<fcntl.h>
#include<unistd.h>
#define FILE_LENGTH 100
int main(int argc,char **argv)
{
int fd1,fd2;
char *pfile=NULL;
char *load=NULL;
int num;
if(argc<3)
{
printf("please input more file ");
return 0;
}
fd1=open(argv[1],O_RDONLY);
fd2=open(argv[2],O_RDWR|O_CREAT,S_IRUSR|S_IWUSR);
printf("fd2=%d ",fd2);
//fd2=open(argv[2],O_WRONLY);
lseek (fd2, FILE_LENGTH+1, SEEK_SET);
write (fd2, "", 1);
lseek (fd2, 0, SEEK_SET);
printf("num=%d ",num);
printf("fd2=%d ",fd2);
pfile=(char*)mmap(0,FILE_LENGTH,PROT_WRITE|PROT_READ,MAP_PRIVATE,fd2,0);
read(fd1,pfile,FILE_LENGTH);
write(fd2,pfile,FILE_LENGTH);
close(fd2);
printf("pfile=%d ",pfile);
munmap(pfile,FILE_LENGTH);
close(fd1);
return 1;
}
管道
#include <sys/mman.h>
#include <sys/types.h>
#include<stdio.h>
#include<string.h>
#include<sys/stat.h>
#include<stdlib.h>
#include<fcntl.h>
#include<unistd.h>
int main ()
{
int fds[2];
pid_t pid;
pipe (fds);
pid = fork ();
if (pid == (pid_t) 0)
{
char str[10000];
sleep(1);
close(fds[1]);
read(fds[0],str,10000);
printf("%s",str);
close(fds[0]);
}
else if(pid>0)
{
FILE*fp;
char a[80];
close(fds[0]);
fp=(fopen("copy1.c","r"));
if(fp==NULL)
{
printf("can not open!!");
exit(0);
}
else
{
while(1)
{
if(fread(a,80,1,fp)==0) break;
write(fds[1],a,sizeof(a));
}
}
wait();
close(fds[1]);
fclose(fp);
return 0;
}