内容由部分确实,等有空了再次个更新
进程间通信的方法
常用API
int pipe(int pipefd[2])
功能:创建一个匿名管道用于进程间通信
参数:int pipefd[2]这是一个传出参数
pipefd[0]:对应的是管道的写端
pipefd[1]:对应的是管道的读端
返回值:成功0,失败-1
管道是默认阻塞的:如果管道中没有数据,read阻塞,如果管道满了,write阻塞
匿名管道只能用于具有关系的进程之间的通信
代码
int main(){
int pipfd[2];
int ret=pipe(pipefd);
if(ret==-1){
perror("pipe");
exit(0);
}
//创建子进程
pid_t pid=fork();
if(pid>0){
printf("i am parent process,pid :%d\n",getpid());
close(pipefd[1]);
char buf[1024]={0};
while(1){
int len=read(pipfd[0],buf,sizeof(buf));
printf(parent recv:%s,pid :%d\n",buf,getpid());
}
}else if(pid==0)
{
printf("i am child process,pid :%d\n",getpid());
close(pipefd[0]);
char buf[1024]={0};
while(1){
char*str="hello,i am child";
write(pipfd[1],str,sizeof(str));
}
}
}
int makefifo(char * pathname,mode_t mode)
参数:
返回值:
write.c
int main(){
int ret=access("test",F_OK);
if(ret==-1){
printf("管道不存在,创建管道\n");
ret=mkfifo("test",0664);
if(ret==-1){
perror("mkfifo");
exit(0);
}
}
int fd=open("text",O_RDONLY);
if(fd==-1){
perror("open");
exit(0);
}
for(int i=0;i<100;++i){
char buf[1024]={0};
sprintf(buf,"hello,%d\n",i);
printf("write data %s\n",buf);
write(fd,buf,sizeof(buf));
}
close(fd);
return 0;
}
read.c
int main(){
int fd=open("text",O_RDONLY);
if(fd==-1){
perror("open");
exit(0);
}
while(1){
char buf[1024]={0};
int len=read(fd,buf,sizeof(buf));
if(len==0){
printf("写端断开连接了...\n");
}
printf("recv buf :%s\n",buf);
}
close(fd);
return 0;
}
共享内存是有效的IPC机制,因为它不涉及进程之间的任何数据传输。这种高效率带来的问题是,我们必须使用其他辅助收单来同步进程对共享内存的访问。否则会产生静态条件。因此共享内存通常和其他进程间通信一起使用
int semget(key_t key,size_t size,int shmflg)
功能
参数
返回值
void* shmat(int shm_id,const void*shm_addr,int shmflg)
功能
参数
int shm_id:由shmget调用返回的共享内存标识符。
const void*shm_addr:指定将共享内存关联到进程的哪块地址空间
null:由操作系统选择,这是推荐的做法,以确保代码的可移植性
非空 且 SHM_RND标志未被设置 :
非空 且 SHM_RND标志被设置 :
int shmflg:
SHM_RDONLY
SHM_REMAP
SHM_EXEC
int mmap(const void * shm_addr)
功能:
int shmctl(int shm_id,int command,struct shmid_ds* buf)
参数
int shm_id:由shm_get返回的内存标识符
int command
IPC_STAT
IPC_SET
void* mmap(void * addr,size_t length,int prot,int flags,int fd,off_t offset)
功能:
参数
void* addr:NULL,有内核指定
size_t length:要映射的数据的长度,这个之不能为0,建议使用文件的长度,获取文件的长度:stat,lseek
int prot:对内存映射区的操作权限
PROT_EXEC:可执行的权限
PROT_READ:读权限
PROT_WRITE:写权限
PROT_NONE:没有权限
int flags
MAP_SHARED:映射区的数据会自动和磁盘文件进行同步,进程间通信,必须要设置这个选型
MAP_PRIVATE:不同步,内存映射区的数据改变了,对原来的文件不会修改,会重新创建一个新的文件
int fd:需要映射的那个文件的文件描述符
通过open得到,open指定的权限不能和prot参数有冲突
off_t offset:偏移量,一般不用,0表示不便宜
void* munmap(void * addr,size_t length)
消息队列是在两个进程之间传递二进制数据的一种简单有效方式。每个数据块都有一个特定的类型,接收方可以根据数据类型来选择地接收数据,而不一定像管道那样必须进行先进先出地方式接收
int msgget(key_t key,int msgflg)
如果msgget用于创建消息队列,与之相关联的内核数据结构msqid_ds将被创建并初始化
int msgsnd(int msqid,const void*msg_ptr,size_t msg_sz,int msgflg)
功能
参数
int msqid:由msgget调用返回的消息队列标识符
const void*msg_ptr:指向一个准备发送的消息,消息必须被定义为如下类型
struct msgbuf{
long mtype;
char mtext[512]
}
size_t msg_sz:消息队列数据部分的长度,这个长度可以为0,表示没有消息队列
int msgflg:控制msgsnd行为,通常仅支持IPC_NOWAIT标志,即以阻塞的方式发送消息。默认情况下,发送消息时如果消息队列满了,则msgsnd将阻塞。若IPC_NOWAIT标志被指定。则msgsnd将立即返回并设置errno为EAGAIN
int msgrcv(int msqid,void*msg_ptr,size_t msg_sz,long int msgtytpe,int msgflg)
功能
参数
int msqid:由msgget调用返回的消息队列标识符
void*msg_ptr:用于存储接收消息
size_t msg_sz:消息队列数据部分的长度
long int msgtytpe
msgtype等于0。读取消息队列中的第一个消息
msgtype大于0。读取消息队列中第一个类型为msgtype的消息
msgtype小于0。读取消息队列中第一个类型值比msgtype的绝对值小的消息
int msgflg:控制msgrcv行为,它可以是如下标志的按位或
IPC_NOWAIT:
IPC_EXCEPT:
IPC_NOERROR:
int msgctl(int msqid,int command,struct msqid_ds*buf)
int msgctl(int msqid,int command,struct msqid_ds*buf)
功能:
-创建一个新的信号量集,或者获取一个 已经存在的信号量集
返回值:
int semop(int sem_id,struct sembuf* semops,size_t num_sem_ops)
参数
struct sembf
{
unsigned short int sem_num;
short int sem_op;
short int sem_flg;
}
sem_num表示信号集中信号量的编号,0表示信号量集中的第一个信号量
sem_op成员指定操作类型,可以选值为正整数,0和负数
sem_flg可选值为IPC_NOWAIT,SEM_UNDO
SEM_NOWAIT的含义是,无论信号操作是否成功,semop调用都立即返回
SEM_UNDO的含义是,当前进程退出时取消正在进行的semop操作。
int semctl(int sem_id,int sem_num,int command,...)
功能
参数
int sem_id:由sem_get调用返回的信号量集标志符,用以指定被操作的信号量集
int sem_num:指定被操作的信号量在信号集中的标号
int command:要执行的命令
IPC_STAT
IPC_SET