當前位置:首頁 » 操作系統 » 源碼量值

源碼量值

發布時間: 2023-07-16 18:45:15

Ⅰ 關於IPC$

程間通信就是在不同進程之間傳播或交換信息,那麼不同進程之間存在著什麼雙方都可以訪問的介質呢?進程的用戶空間是互相獨立的,一般而言是不能互相訪問的,唯一的例外是共享內存區。但是,系統空間卻是「公共場所」,所以內核顯然可以提供這樣的條件。除此以外,那就是雙方都可以訪問的外設了。在這個意義上,兩個進程當然也可以通過磁碟上的普通文件交換信息,或者通過「注冊表」或其它資料庫中的某些表項和記錄交換信息。廣義上這也是進程間通信的手段,但是一般都不把這算作「進程間通信」。因為那些通信手段的效率太低了,而人們對進程間通信的要求是要有一定的實時性。
進程間通信主要包括管道, 系統IPC(包括消息隊列,信號量,共享存儲), SOCKET.
管道包括三種:1)普通管道PIPE, 通常有種限制,一是半雙工,只能單向傳輸;二是只能在父子進程間使用. 2)流管道s_pipe: 去除了第一種限制,可以雙向傳輸. 3)命名管道:name_pipe, 去除了第二種限制,可以在許多並不相關的進程之間進行通訊.
系統IPC的三種方式類同,都是使用了內核里的標識符來識別.
FAQ1: 管道與文件描述符,文件指針的關系?
答: 其實管道的使用方法與文件類似,都能使用read,write,open等普通IO函數. 管道描述符來類似於文件描述符. 事實上, 管道使用的描述符, 文件指針和文件描述符最終都會轉化成系統中SOCKET描述符. 都受到系統內核中SOCKET描述符的限制. 本質上LINUX內核源碼中管道是通過空文件來實現.
FAQ2: 管道的使用方法?
答: 主要有下面幾種方法: 1)pipe, 創建一個管道,返回2個管道描述符.通常用於父子進程之間通訊. 2)popen, pclose: 這種方式只返回一個管道描述符,常用於通信另一方是stdin or stdout; 3)mkpipe: 命名管道, 在許多進程之間進行交互.
FAQ3: 管道與系統IPC之間的優劣比較?
答: 管道: 優點是所有的UNIX實現都支持, 並且在最後一個訪問管道的進程終止後,管道就被完全刪除;缺陷是管道只允許單向傳輸或者用於父子進程之間.
系統IPC: 優點是功能強大,能在毫不相關進程之間進行通訊; 缺陷是關鍵字KEY_T使用了內核標識,佔用了內核資源,而且只能被顯式刪除,而且不能使用SOCKET的一些機制,例如select,epoll等.
FAQ4: WINDOS進程間通信與LINUX進程間通信的關系?
答: 事實上,WINDOS的進程通信大部分移植於UNIX, WINDOS的剪貼板,文件映射等都可從UNIX進程通信的共享存儲中找到影子.
FAQ5: 進程間通信與線程間通信之間的關系?
答: 因為WINDOWS運行的實體是線程, 狹義上的進程間通信其實是指分屬於不同進程的線程之間的通訊.而單個進程之間的線程同步問題可歸並為一種特殊的進程通信.它要用到內核支持的系統調用來保持線程之間同步. 通常用到的一些線程同步方法包括:Event, Mutex, 信號量Semaphore, 臨界區資源等.
Linux的進程間通信(IPC,InterProcess Communication)通信方法有管道、消息隊列、信號量、共享內存、套介面等。
管道分為有名管道和無名管道,無名管道只能用於親屬進程之間的通信,而有名管道則可用於無親屬關系的進程之間。
#define INPUT 0
#define OUTPUT 1
void main()
{
int file_descriptors[2];
/*定義子進程號 */
pid_t pid;
char buf[BUFFER_LEN];
int returned_count;
/*創建無名管道*/
pipe(file_descriptors);
/*創建子進程*/
if ((pid = fork()) == - 1)
{
printf("Error in fork\n");
exit(1);
}
/*執行子進程*/
if (pid == 0)
{
printf("in the spawned (child) process...\n");
/*子進程向父進程寫數據,關閉管道的讀端*/
close(file_descriptors[INPUT]);
write(file_descriptors[OUTPUT], "test data", strlen("test data"));
exit(0);
}
else
{
/*執行父進程*/
printf("in the spawning (parent) process...\n");
/*父進程從管道讀取子進程寫的數據,關閉管道的寫端*/
close(file_descriptors[OUTPUT]);
returned_count = read(file_descriptors[INPUT], buf, sizeof(buf));
printf("%d bytes of data received from spawned process: %s\n",
returned_count, buf);
}
}
上述程序中,無名管道以int pipe(int filedis[2]);方式定義,參數filedis返回兩個文件描述符filedes[0]為讀而打開,filedes[1]為寫而打開,filedes[1]的輸出是filedes[0]的輸入;
在Linux系統下,有名管道可由兩種方式創建(假設創建一個名為「fifoexample」的有名管道):
(1)mkfifo("fifoexample","rw");
(2)mknod fifoexample p
mkfifo是一個函數,mknod是一個系統調用,即我們可以在shell下輸出上述命令。
有名管道創建後,我們可以像讀寫文件一樣讀寫之:
/* 進程一:讀有名管道*/
void main()
{
FILE *in_file;
int count = 1;
char buf[BUFFER_LEN];
in_file = fopen("pipeexample", "r");
if (in_file == NULL)
{
printf("Error in fdopen.\n");
exit(1);
}
while ((count = fread(buf, 1, BUFFER_LEN, in_file)) > 0)
printf("received from pipe: %s\n", buf);
fclose(in_file);
}
/* 進程二:寫有名管道*/
void main()
{
FILE *out_file;
int count = 1;
char buf[BUFFER_LEN];
out_file = fopen("pipeexample", "w");
if (out_file == NULL)
{
printf("Error opening pipe.");
exit(1);
}
sprintf(buf, "this is test data for the named pipe example\n");
fwrite(buf, 1, BUFFER_LEN, out_file);
fclose(out_file);
}
消息隊列用於運行於同一台機器上的進程間通信,與管道相似;
共享內存通常由一個進程創建,其餘進程對這塊內存區進行讀寫。得到共享內存有兩種方式:映射/dev/mem設備和內存映像文件。前一種方式不給系統帶來額外的開銷,但在現實中並不常用,因為它控制存取的是實際的物理內存;常用的方式是通過shmXXX函數族來實現共享內存:
int shmget(key_t key, int size, int flag); /* 獲得一個共享存儲標識符 */
該函數使得系統分配size大小的內存用作共享內存;
void *shmat(int shmid, void *addr, int flag); /* 將共享內存連接到自身地址空間中*/
shmid為shmget函數返回的共享存儲標識符,addr和flag參數決定了以什麼方式來確定連接的地址,函數的返回值即是該進程數據段所連接的實際地址。此後,進程可以對此地址進行讀寫操作訪問共享內存。
本質上,信號量是一個計數器,它用來記錄對某個資源(如共享內存)的存取狀況。一般說來,為了獲得共享資源,進程需要執行下列操作:
(1)測試控制該資源的信號量;
(2)若此信號量的值為正,則允許進行使用該資源,進程將進號量減1;
(3)若此信號量為0,則該資源目前不可用,進程進入睡眠狀態,直至信號量值大於0,進程被喚醒,轉入步驟(1);
(4)當進程不再使用一個信號量控制的資源時,信號量值加1,如果此時有進程正在睡眠等待此信號量,則喚醒此進程。
下面是一個使用信號量的例子,該程序創建一個特定的IPC結構的關鍵字和一個信號量,建立此信號量的索引,修改索引指向的信號量的值,最後清除信號量:
#include <stdio.h>
#include <sys/types.h>
#include <sys/sem.h>
#include <sys/ipc.h>
void main()
{
key_t unique_key; /* 定義一個IPC關鍵字*/
int id;
struct sembuf lock_it;
union semun options;
int i;
unique_key = ftok(".", 'a'); /* 生成關鍵字,字元'a'是一個隨機種子*/
/* 創建一個新的信號量集合*/
id = semget(unique_key, 1, IPC_CREAT | IPC_EXCL | 0666);
printf("semaphore id=%d\n", id);
options.val = 1; /*設置變數值*/
semctl(id, 0, SETVAL, options); /*設置索引0的信號量*/
/*列印出信號量的值*/
i = semctl(id, 0, GETVAL, 0);
printf("value of semaphore at index 0 is %d\n", i);
/*下面重新設置信號量*/
lock_it.sem_num = 0; /*設置哪個信號量*/
lock_it.sem_op = - 1; /*定義操作*/
lock_it.sem_flg = IPC_NOWAIT; /*操作方式*/
if (semop(id, &lock_it, 1) == - 1)
{
printf("can not lock semaphore.\n");
exit(1);
}
i = semctl(id, 0, GETVAL, 0);
printf("value of semaphore at index 0 is %d\n", i);
/*清除信號量*/
semctl(id, 0, IPC_RMID, 0);
}
套接字通信並不為Linux所專有,在所有提供了TCP/IP協議棧的操作系統中幾乎都提供了socket,而所有這樣操作系統,對套接字的編程方法幾乎是完全一樣的。
進程間通信各種方式效率比較
類型
無連接
可靠
流控制
記錄
消息類型優先順序

熱點內容
怎麼搭建linux伺服器ftp 發布:2025-03-16 07:07:38 瀏覽:987
晶元存儲原理 發布:2025-03-16 06:58:21 瀏覽:284
c語言中的整型 發布:2025-03-16 06:40:48 瀏覽:184
分部資料庫伺服器的IP地址有效 發布:2025-03-16 06:33:40 瀏覽:192
安卓項目如何配置tomacat 發布:2025-03-16 06:31:13 瀏覽:431
寫腳本測試 發布:2025-03-16 06:20:07 瀏覽:780
多個撥號寬頻如何配置 發布:2025-03-16 05:51:35 瀏覽:688
管理員c語言 發布:2025-03-16 05:40:17 瀏覽:342
安卓軟體上的圖案如何更改 發布:2025-03-16 05:35:57 瀏覽:748
2010編譯c中文亂碼 發布:2025-03-16 05:33:40 瀏覽:550