Linux进程间的通信

1、管道(Pipe)

用的api函数有:pipe

示例:

//pipe.c
#include <unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>

int main(int agrc ,char *argv[])
{
		int fdset[2];
		pid_t pid;
		int r_num;
		char buf_r[100];
		
		pipe(fdset);

		pid = fork();

		if(pid == 0)
		{
			//子进程
			printf("child progress running...\n");
			//关闭写管道
			close(fdset[1]);
			//睡眠2s,等待父进程写
			sleep(2);
			if((r_num=read(fdset[0],buf_r,100))>0)
			{
				printf("%d numbers read from the pipe is %s\n",r_num,buf_r);
			}	
			close(fdset[0]);
			exit(0);
		}
		else
		{
			//父进程
			printf("parent progress running...\n");
			//关闭读管道
			close(fdset[0]);
			
			if(write(fdset[1],"hello,world!\n",13) != -1)
			{
						printf("parent write \'hello,world!\'\n");
			}
			
			close(fdset[1]);
			waitpid(pid,NULL,0);
			exit(0);

		}
}	

注意:fdset[0]为读端,fdset[1]写端。

2、有名管道(named pipe)

用的api函数有:mkfifo

示例:

//mkfifo_w.c
#include<stdlib.h>
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include <fcntl.h>
 #include <string.h>
 
#define FIFO "/my_fifo"


int main(int argc, char *agrv[])
{
				int fd;
        int res = mkfifo(FIFO, 0777);
        if(res == 0)
        {
                printf("FIFO created\n");
        }
        
        fd = open(FIFO, O_WRONLY|O_NONBLOCK, 0);
        if(fd == -1)
        {
                perror("open");
                exit(1);
        }
        
        if(argc < 2)
        {
                perror("argc");
                exit(1);
        }
        
        
        if((write(fd,agrv[1],strlen(agrv[1])))== -1)
				{
							printf("The FIFO has not been read yet.Please try later\n");
				}
				else
							printf("write %s to the FIFO\n");
							
				close(fd);
        
        exit(EXIT_SUCCESS);
}

//mkfifo_r.c

#include<errno.h>
#include<sys/stat.h>
#include<fcntl.h>

FIFO "/tmp/my_fifo"
//本程序从一个FIFO读数据,并把读到的数据打印到标准输出
//如果读到字符“Q”,则退出
int main(int argc, char** argv)
{
        char buf_r[100];
        int fd;
        int nread;
        if((mkfifo(FIFO, O_CREAT) < 0) && (errno != EEXIST))
        {
                printf("不能创建FIFO\n");
                exit(1);
        }

        printf("准备读取数据\n");
        fd = open(FIFO, O_RDONLY, 0);
        if(fd == -1)
        {
                perror("打开FIFO");
                exit(1);
        }

        while(1)
        {
                if((nread = read(fd, buf_r, 100)) == -1)
                {
                        if(errno == EAGAIN) printf("没有数据\n");
                }

                //假设取到Q的时候退出
                if(buf_r[0]=='Q') break;

                buf_r[nread]=0;
                printf("从FIFO读取的数据为:%s\n", buf_r);
                sleep(1);
        }

}

3、共享内存

用的api函数有:ftok、shmget、shmdt

示例:

//shm_com.h

#define TEXT_SZ 2048

struct shared_use_st
{
    int written_by_you;
	char some_text[TEXT_SZ];
};

#define KEY_PATH "etc/config.ini"
#define KEY_ID    111

//shm1.c
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include "shm_com.h"



/*
 * 程序入口
 * */
int main(void)
{
	key_t kyt;
	
  int running=1;
	void *shared_memory=(void *)0;
	struct shared_use_st *shared_stuff;
	int shmid;
	kyt = ftok(KEY_PATH,KEY_ID);
	/*创建共享内存*/
	
	shmid=shmget(kyt,sizeof(struct shared_use_st),0666|IPC_CREAT);
	if(shmid==-1)
	{
	    fprintf(stderr,"shmget failed\n");
		exit(EXIT_FAILURE);
	}

	/*映射共享内存*/
	shared_memory=shmat(shmid,(void *)0,0);
	if(shared_memory==(void *)-1)
	{
	    fprintf(stderr,"shmat failed\n");
		exit(EXIT_FAILURE);
	}
	printf("Memory attached at %X\n",(int)shared_memory);

	/*让结构体指针指向这块共享内存*/
	shared_stuff=(struct shared_use_st *)shared_memory;

	/*控制读写顺序*/
	shared_stuff->written_by_you=0;
	/*循环的从共享内存中读数据,直到读到“end”为止*/
	while(running)
	{
	   if(shared_stuff->written_by_you)
	   {
	       printf("You wrote:%s",shared_stuff->some_text);
		   sleep(1);  //读进程睡一秒,同时会导致写进程睡一秒,这样做到读了之后再写
		   shared_stuff->written_by_you=0;
		   if(strncmp(shared_stuff->some_text,"end",3)==0)
		   {
		       running=0; //结束循环
		   }
	   }
	}
	/*删除共享内存*/
	if(shmdt(shared_memory)==-1)
	{
	    fprintf(stderr,"shmdt failed\n");
	    exit(EXIT_FAILURE);
	}
       exit(EXIT_SUCCESS);
}

//shm2.c
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include "shm_com.h"

/*
 * 程序入口
 * */
int main(void)
{
  int running=1;
  key_t kyt;
	void *shared_memory=(void *)0;
	struct shared_use_st *shared_stuff;
	char buffer[BUFSIZ];
	int shmid;
	kyt = ftok(KEY_PATH,KEY_ID);
	/*创建共享内存*/
	shmid=shmget(kyt,sizeof(struct shared_use_st),0666|IPC_CREAT);
	if(shmid==-1)
	{
	    fprintf(stderr,"shmget failed\n");
		exit(EXIT_FAILURE);
	}

	/*映射共享内存*/
	shared_memory=shmat(shmid,(void *)0,0);
	if(shared_memory==(void *)-1)
	{
	    fprintf(stderr,"shmat failed\n");
		exit(EXIT_FAILURE);
	}
	printf("Memory attached at %X\n",(int)shared_memory);

	/*让结构体指针指向这块共享内存*/
	shared_stuff=(struct shared_use_st *)shared_memory;
	/*循环的向共享内存中写数据,直到写入的为“end”为止*/
	while(running)
	{
	    while(shared_stuff->written_by_you==1)
		{
		    sleep(1);//等到读进程读完之后再写
			printf("waiting for client...\n");
		}
		printf("Ener some text:");
		fgets(buffer,BUFSIZ,stdin);
		strncpy(shared_stuff->some_text,buffer,TEXT_SZ);
		shared_stuff->written_by_you=1;
		if(strncmp(buffer,"end",3)==0)
		{
		    running=0;  //结束循环
		}
	}
	/*删除共享内存*/
	if(shmdt(shared_memory)==-1)
	{
	    fprintf(stderr,"shmdt failed\n");
		exit(EXIT_FAILURE);
	}
	exit(EXIT_SUCCESS);
}


4、消息队列

用的api函数有:msgget、msgrcv、msgsnd、msgctl

示例:

/*msg.c*/
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define BUFSZ 512
struct message{
	long msg_type;
	char msg_text[BUFSZ];
};
int main()
{
	int qid;
	key_t key;
	int len;
	struct message msg;
	/*根据不同的路径和关键表示产生标准的key*/
	if((key=ftok(".",'a'))== 1){
		perror("ftok");
		exit(1);
	}
	/*创建消息队列*/
	if((qid=msgget(key,IPC_CREAT|0666))== 1){
		perror("msgget");
		exit(1);
	}
	printf("opened queue %d\n",qid);
	puts("Please enter the message to queue:");
	if((fgets((&msg)->msg_text,BUFSZ,stdin))==NULL){
		puts("no message");
		exit(1);
	}
	msg.msg_type = getpid();
	len = strlen(msg.msg_text);
	/*添加消息到消息队列*/
	if((msgsnd(qid,&msg,len,0))<0){
		perror("message posted");
		exit(1);
	}
	/*读取消息队列*/
	if(msgrcv(qid,&msg,BUFSZ,0,0)<0){
		perror("msgrcv");
		exit(1);
	}
	printf("message is:%s\n",(&msg)->msg_text);
	/*从系统内核中移走消息队列。*/
	if((msgctl(qid,IPC_RMID,NULL))<0){
		perror("msgctl");
		exit(1);
	}
	exit(0);
}

5、进程信号量

用的api函数有:semgetsemop

示例:

#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
 #include <sys/ipc.h>
 #include <sys/shm.h>
 
 #define BUFFER_SIZE 2048
 
 int main() {
     pid_t pid;
     int shmid;
     char *shm_addr;
     char flag[]="Parent";
     char buff[BUFFER_SIZE];
 //    创建当前进程的私有共享内存
     if ((shmid=shmget(IPC_PRIVATE,BUFFER_SIZE,0666))<0) {
         perror("shmget");
         exit(1);
     } else 
         printf("Create shared memory: %d.\n",shmid);
 
 //    ipcs 命令往标准输出写入一些关于活动进程间通信设施的信息
 //    -m 表示共享内存
     printf("Created shared memory status:\n");
     system("ipcs -m");
 
     if((pid=fork())<0) {
         perror("fork");
         exit(1);
     }else if (pid==0) {
 //    自动分配共享内存映射地址,为可读可写,映射地址返回给shm_addr
         if ((shm_addr=shmat(shmid,0,0))==(void*)-1) {
             perror("Child:shmat");
             exit(1);
         }else
             printf("Child: Attach shared-memory: %p.\n",shm_addr);
 
         printf("Child Attach shared memory status:\n");
         system("ipcs -m");
 //    比较shm_addr,flag的长度为strlen(flag)的字符
 //    当其内容相同时,返回0
 //    否则返回(str1[n]-str2[n])
         while (strncmp(shm_addr,flag,strlen(flag))) {
             printf("Child: Waiting for data...\n");
             sleep(10);
         }
 
         strcpy(buff,shm_addr+strlen(flag));
         printf("Child: Shared-memory: %s\n",buff);
 //    删除子进程的共享内存映射地址
         if (shmdt(shm_addr)<0) {
             perror("Child:shmdt");
             exit(1);
         }else
             printf("Child: Deattach shared-memory.\n");
 
         printf("Child Deattach shared memory status:\n");
         system("ipcs -m");
 
     }else{
         sleep(1);
 //    自动分配共享内存映射地址,为可读可写,映射地址返回给shm_addr
         if ((shm_addr=shmat(shmid,0,0))==(void*)-1) {
             perror("Parent:shmat");
             exit(1);
         }else
             printf("Parent: Attach shared-memory: %p.\n",shm_addr);
 
         printf("Parent Attach shared memory status:\n");
         system("ipcs -m");
 //    shm_addr为flag+stdin
         sleep(1);
         printf("\nInput string:\n");
         fgets(buff,BUFFER_SIZE-strlen(flag),stdin);
         strncpy(shm_addr+strlen(flag),buff,strlen(buff));
         strncpy(shm_addr,flag,strlen(flag));
 //    删除父进程的共享内存映射地址
         if (shmdt(shm_addr)<0) {
             perror("Parent:shmdt");
             exit(1);
         }else
             printf("Parent: Deattach shared-memory.\n");
 
         printf("Parent Deattach shared memory status:\n");
         system("ipcs -m");
 //    保证父进程在删除共享内存前,子进程能读到共享内存的内容        
         waitpid(pid,NULL,0);
 //    删除共享内存
         if (shmctl(shmid,IPC_RMID,NULL)==-1) {
             perror("shmct:IPC_RMID");
             exit(1);
         }else
             printf("Delete shared-memory.\n");
 
         printf("Child Delete shared memory status:\n");
         system("ipcs -m");
 
         printf("Finished!\n");
     }
     
     exit(0);
 }


 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值