Linux下C編程:進程間通信(IPC)總結

(1)Linux信號:

某種信號相當於某種事件,一般用於內核告訴進程某種事件發生了,進程通過signal函數註冊信號的處理函數。我個人體會在用戶態中兩個進程之間用信號進行進程間通信應該不是一個特別好的方法,限制比較多。

(2)匿名管道:

int pipe(int fdes[2]);//創建匿名管道

管道的都寫方法和文件文件讀寫方法相同

匿名管道一般用在父進程和子進程之間的數據通信,而且匿名管道是在內核中臨時存儲的,程序運行結束後,就不存在了。

(3)命名管道:任何兩個進程之間都可以通過命名管道去通信,命名管道是作爲特殊設備文件存儲在文件系統中的,當程序運行結束後,它繼續存在於文件系統中,除非刪除該文件。Linix Shell中可以看到命名管道文件名後面緊跟一個|,可以通過S_ISFIFO宏來檢測一個文件是否是命名管道。

下面給出一個通過命名管道通信的一個客戶端-服務端程序,實現的功能是客戶端在終端輸入字符串,寫入管道,服務器端從管道讀出字符串,並顯示在終端上。具體的可以參加《精通Linux C編程一書》

服務器端程序:

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/stat.h>

#define FIFO_FILE "MYFIFO"

int main()
{
	FILE *fp;
	char readbuf[80];
	if((fp=fopen(FIFO_FILE,"r"))==NULL)
	{
		umask(0);
		mknod(FIFO_FILE,S_IFIFO|0666,0);
	}
	else 
		fclose(fp);
	while(1)
	{
		if((fp=fopen(FIFO_FILE,"r"))==NULL)
		{
			printf("open fifo failed. \n");
			exit(1);
		}
		if(fgets(readbuf,80,fp)!=NULL)
		{
			printf("Received string :%s \n", readbuf);
			fclose(fp);
		}
		else
		{
			if(ferror(fp))
			{
				printf("read fifo failed.\n");
				exit(1);
			}
		}
	}
	return 0;
}
客戶端程序:
#include <stdio.h>
#include <stdlib.h>

#define FIFO_FILE "MYFIFO"

int main(int argc, char *argv[])
{
	FILE *fp;
	int i;
	if(argc<=1)
	{
		printf("usage: %s <pathname>\n",argv[0]);
		exit(1);
	}
	if((fp=fopen(FIFO_FILE,"w"))==NULL)
	{
		printf("open fifo failed. \n");
		exit(1);
	}
	for(i=1;i<argc;i++)
	{
		if(fputs(argv[i],fp)==EOF)
		{
			printf("write fifo error. \n");
			exit(1);
		}
		if(fputs(" ",fp)==EOF)
		{
			printf("write fifo error. \n");
			exit(1);
		}
	}
	fclose(fp);
	return 0;
}

除了上面三種方法,Linux還支持Unix System V的IPC機制,消息隊列、信號量及共享內存,這幾種方法在編程接口和內部實現上都非常像。


(4)消息隊列:

int msgget(key_t key, int flag); //創建或打開消息隊列

int msgsnd(int msqid, const void* ptr, size_t nbyte, in flag); //向消息隊列發送消息

int msgrcv(int msqid, const void* ptr, size_t nbyte, long type in flag); //從消息隊列中取出消息

個人感覺消息隊列用於進程間的通信是非常靈活和方便的。


(5)信號量:

信號量實際是一個整型計數器,主要用來控制多個進程對共享資源的訪問,比如實現關鍵區。


(6)共享內存:

和Windows中的內存映射文件類似,用共享內存文件進行進程間數據交換的最大好處我認爲就是簡單,每個進程訪問共享內存的時候和訪問其他內存沒什麼區別。不過共享內存有一個問題是,如果多個進程同時對共享內存進行修改,則需要通過信號量等機制進行同步控制。

int shmget(key_t key, int size, int flag); //創建或打開共享內存

void * shmat(int shmid, void *addr, int flag); //將共享內存附加到進程的地址空間中

int shmdt(void *addr); //取消共享內存和進程的地址空間的關係




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章