linux下C語言編程4-使用共享內(nèi)存實(shí)現(xiàn)進(jìn)程間通信_(tái)第1頁
linux下C語言編程4-使用共享內(nèi)存實(shí)現(xiàn)進(jìn)程間通信_(tái)第2頁
linux下C語言編程4-使用共享內(nèi)存實(shí)現(xiàn)進(jìn)程間通信_(tái)第3頁
linux下C語言編程4-使用共享內(nèi)存實(shí)現(xiàn)進(jìn)程間通信_(tái)第4頁
linux下C語言編程4-使用共享內(nèi)存實(shí)現(xiàn)進(jìn)程間通信_(tái)第5頁
已閱讀5頁,還剩7頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、linux下C語言編程4-使用共享內(nèi)存實(shí)現(xiàn)進(jìn)程間通信共享內(nèi)存的函數(shù)有以下幾個(gè):(1)int shmget(key_t key, int size, int shmflg),開辟或使用一塊共享內(nèi)存。(2)void *shmat(int shmid, const void *shmaddr, int shmflg), 將參數(shù)shmid所指向的共享內(nèi)存與當(dāng)前進(jìn)程連接。當(dāng)使用某共享內(nèi)存時(shí),需要先使用shmat,達(dá)成連接。(3)int shmdt(const void *shmaddr),將先前用shmat連接的共享內(nèi)存與當(dāng)前進(jìn)程解除連接。參數(shù)shmaddr為shmat返回的共享內(nèi)存的地址。在完成對(duì)共享

2、內(nèi)存的使用后,需要使用shmdt解除連接。(4)int shmctl(int shmid, int cmd, struct shmid_ds *buf),控制內(nèi)存的操作。當(dāng)cmd為IPC_RMID時(shí),刪除shmid所指的共享內(nèi)存。這些函數(shù)的表頭文件為<sys/ipc.h>和<sys/shm.h>,其詳細(xì)參數(shù)請(qǐng)去網(wǎng)上搜索。下面給出一個(gè)使用共享內(nèi)存實(shí)現(xiàn)進(jìn)程間通信的例子:進(jìn)程A開辟一塊新的共享內(nèi)存,進(jìn)程B修改這個(gè)共享內(nèi)存,進(jìn)程C打印輸出這個(gè)共享內(nèi)存的內(nèi)容,進(jìn)程D刪除這個(gè)共享內(nèi)存。 進(jìn)程BCD運(yùn)行的命令格式為:命令 共享內(nèi)存ID,如./output 123432。進(jìn)程A代碼如下

3、:int main()int shmid;shmid = shmget(IPC_PRIVATE, SIZE, IPC_CREAT | 0600);if (shmid < 0)perror("shmget error");exit(1);printf("create shared memory OK. shmid=%d/n", shmid);return 0;進(jìn)程B代碼如下:int main(int argc, char *argv)int shmid;char *shmaddr;if (argc != 2)perror("argc err

4、or/n"); exit(1);shmid = atoi(argv1);shmaddr = (char *)shmat(shmid, NULL, 0); if (int )shmaddr = -1)perror("shmat error./n"); exit(1);strcpy(shmaddr, "hello, world!"); shmdt(shmaddr);return 0;進(jìn)程C代碼如下:int main(int argc, char *argv)int shmid;char *shmaddr;if (argc != 2)printf(&

5、quot;argc error/n"); exit(1);shmid = atoi(argv1);shmaddr = (char *)shmat(shmid, NULL, 0); if (int )shmaddr = -1)perror("shmat error./n"); exit(1);printf("%s/n", shmaddr);shmdt(shmaddr);return 0;進(jìn)程D代碼如下:int main(int argc, char *argv)int shmid;if (argc != 2)perror("argc e

6、rror/n");exit(1);shmid = atoi(argv1);shmctl(shmid, IPC_RMID, NULL);return 0;linux下C語言編程5-多線程編程Linux系統(tǒng)下的多線程遵循POSIX線程接口,稱為pthread。編寫Linux下的多線程程序,需要使用頭文件pthread.h,編譯需要在后面加-lpthread。關(guān)于多線程,主要有以下幾個(gè)過程:1,創(chuàng)建線程2,各個(gè)線程的執(zhí)行3,等待線程的結(jié)束涉及的線程函數(shù)主要有:1,int pthread_create(pthread_t *restrict tidp, const pthread_attr_

7、t *restrict attr, void *(*start_rtn)(void), void *restrict arg);函數(shù)有4個(gè)參數(shù):第一個(gè)參數(shù)為指向線程標(biāo)識(shí)符的指針。第二個(gè)參數(shù)用來設(shè)置線程屬性。第三個(gè)參數(shù)是一個(gè)函數(shù)指針(有關(guān)函數(shù)指針,看這里),指向線程運(yùn)行函數(shù)的起始地址。最后一個(gè)參數(shù)是函數(shù)指針?biāo)枰膮?shù)。注意:pthread_create函數(shù)返回0表示成功。另外如果函數(shù)指針需要多個(gè)參數(shù)的話,就將這些參數(shù)做成某個(gè)結(jié)構(gòu)體,作為第4個(gè)參數(shù)。如果有返回值的話,也可將返回值的指針回寫到第4個(gè)參數(shù)中。2,pthread_join()等待一個(gè)線程的結(jié)束。pthread_exit()用于線程退出

8、,可以指定返回值,以便其他線程通過pthread_join()函數(shù)獲取該線程的返回值。線程的應(yīng)用:并行數(shù)據(jù)庫的查詢假設(shè)我們有3臺(tái)計(jì)算機(jī)A, B, C,每臺(tái)均安裝PG數(shù)據(jù)庫,通過網(wǎng)絡(luò)連接。我們可以通過多線程將查詢SQL廣播出去,A,B,C并行查詢,最終返回各自的結(jié)果。如果沒有多線程,而只是用了個(gè)循環(huán),那么我們獲取結(jié)果的過程將是順序的,即等A的結(jié)果返回后才能查詢B,B結(jié)束后查詢C,效率低下。代碼如下:/最多支持MAX個(gè)線程 #define MAX 16/* 多線程 */typedef struct PDthreadchar *host; / IPint port; / 端口char *dbname

9、; / 數(shù)據(jù)庫名char *query; / SQL語句void *rst; / 查詢結(jié)果PDthread;typedef struct Nodesint count; / 實(shí)際上的節(jié)點(diǎn)數(shù)量count<=MAXchar hostMAX32;int portMAX;Nodes; /* 線程的執(zhí)行過程,參數(shù)m為PDthread結(jié)構(gòu) */void *PDthreadSelect(void *m)PDthread *p = (PDthread *)m;p->rst = (void *)ExecuteQuery(p->host, p->port, p->dbname, p-

10、>query); pthread_exit(NULL);return NULL; /* 創(chuàng)建多個(gè)線程,1個(gè)node對(duì)應(yīng)1個(gè)線程 * 輸出:thread, pdthread * 輸入:node, dbname, query, 這些值寫到pdthread變量中,傳遞給函數(shù)PDthreadSelect(因?yàn)榇撕瘮?shù)只能有一個(gè)參數(shù)) */void PDthreadCreate(pthread_t thread, PDthread *pdthread, Nodes *node, char *dbname, char *query)int tmp;int i;PDthread *p;for (i=0;

11、 i<node->count; i+)/ 把Nodes作為PDthread的一部分p = pdthread + i;p->host = node->hosti;p->port = node->porti;p->dbname = dbname;p->query = query;tmp = pthread_create(&threadi, NULL, PDthreadSelect, p); if (tmp != 0) printf("PDthreadCreate: 線程%d創(chuàng)建失敗!/n", i);else printf(

12、"PDthreadCreate: 線程%d被創(chuàng)建/n", i);void PDthreadWait(pthread_t thread, int count)/ 等待線程結(jié)束int i;for (i=0; i<count; i+)if (threadi != 0)pthread_join(threadi,NULL);printf("線程%d已經(jīng)結(jié)束/n", i);int main()Nodes node; node.count = 3;strcpy(node.host0, "192.168.0.1");node.port0 = 5

13、432;strcpy(node.host1, "192.168.0.2");node.port1 = 5432;strcpy(node.host2, "192.168.0.3");node.port2 = 5432; /使用多線程去獲取數(shù)據(jù)pthread_t threadMAX;memset(&thread, 0, sizeof(thread); / 獲取結(jié)果PDthread *pdthread = (PDthread *)malloc(node.count * sizeof(PDthread);PDthreadCreate(thread, pd

14、thread, &node, "database", "SELECT * FROMstudent");PDthreadWait(thread, node.count); / 返回結(jié)果存儲(chǔ)在pdthread->rstreturn 0;編譯命令:gcc -I/usr/local/pgsql/include -o th th.c -L/usr/local/pgsql/lib -lpq -lpthread,因?yàn)槭褂昧薼ibpq庫。Linux下通過共享內(nèi)存進(jìn)行進(jìn)程間通信,進(jìn)程間同步使用信號(hào)量來實(shí)現(xiàn)(Linux 環(huán)境下C編程指南)Linux 環(huán)境下C編

15、程指南,通過共享內(nèi)存進(jìn)行進(jìn)程間通信的例子,進(jìn)程間同步使用信號(hào)量來實(shí)現(xiàn)。使用說明:這是一個(gè)簡單的服務(wù)器和客戶端程序,如果啟動(dòng)程序時(shí)不帶參數(shù),則執(zhí)行服務(wù)器程序;如果帶參數(shù),則執(zhí)行客戶端程序,所帶參數(shù)只有一個(gè),就是服務(wù)器端所顯示的共享內(nèi)存的引用ID。實(shí)現(xiàn)原理:服務(wù)器端啟動(dòng)后,創(chuàng)建信號(hào)量和共享內(nèi)存,并將共享內(nèi)存的引用ID顯示出來,將信號(hào)量的引用ID存放在共享內(nèi)存中。客戶端啟動(dòng)后,利用服務(wù)器端提供的內(nèi)存共享ID將共享內(nèi)存附加到地址段,讀取信號(hào)量以實(shí)現(xiàn)兩個(gè)進(jìn)程之間的同步。之后,這兩個(gè)進(jìn)程就可以利用共享內(nèi)存進(jìn)行進(jìn)程間通信,客戶端輸入的信息將在服務(wù)器端顯示出來。#include <stdlib.h>

16、;#include <errno.h>#include <string.h>#include <signal.h>#include <stdio.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>#include <sys/shm.h>#define SHMDATASIZE 1000#define BUFFERSIZE (SHMDATASIZE - sizeof(int)#define SN_EMPTY 0#define

17、SN_FULL 1int deleteSemid=0;union semunint val;struct semid_ds *buf;unsigned short int *array;struct seminfo *_buf;void server(void); /不加參數(shù)時(shí)執(zhí)行void client(int shmid);void delete(void);void sigdelete(int signum);void locksem(int semid, int semnum);void unlocksem(int semid, int semnum);void waitzero(int

18、 semid, int semnum);void clientwrite(int shmid, int semid, char *buffer);int safesemget(key_t key, int nsems, int semflg);int safesemctl(int semid, int semnum, int cmd, union semun arg); int safesemop(int semid, struct sembuf *sops, unsigned nsops); int safeshmget(key_t key, int size, int shmflg);vo

19、id *safeshmat(int shmid, const void *shmaddr, int shmflg);int safeshmctl(int shmid, int cmd, struct shmid_ds *buf);int main(int argc, char *argv)if ( argc < 2 )server();elseclient(atoi(argv1);return 0;void server(void)union semun sunion;int semid,shmid;void *shmdata;char *buffer;semid = safesemge

20、t(IPC_PRIVATE, 2, SHM_R|SHM_W);deleteSemid = semid;atexit(&delete); /當(dāng)程序終止執(zhí)行時(shí),執(zhí)行 delete 函數(shù)signal(SIGINT, &sigdelete); /接收到信號(hào) SIGINT 則執(zhí)行 sigdelete 函數(shù) sunion.val = 1;safesemctl(semid, SN_EMPTY, SETVAL, sunion);sunion.val = 0;safesemctl(semid, SN_FULL, SETVAL, sunion);shmid = safeshmget(IPC_PRI

21、VATE, SHMDATASIZE, IPC_CREAT|SHM_R|SHM_W);shmdata = safeshmat(shmid, 0, 0);safeshmctl(shmid, IPC_RMID, NULL); /刪除共享內(nèi)存,當(dāng)所有附加該共享內(nèi)存的進(jìn)程結(jié)束或斷開與該共享內(nèi)存的連接時(shí)才執(zhí)行*(int *)shmdata = semid;buffer = shmdata + sizeof(int);printf("Server is running with SHM id * %d *n", shmid);while(1)printf("Waiting un

22、til full.");fflush(stdout);locksem(semid, SN_FULL);printf("done.n");printf("Message received: %s.n", buffer);unlocksem(semid, SN_EMPTY);void client(int shmid)int semid;void *shmdata;char *buffer;shmdata = safeshmat(shmid, 0, 0);semid = *(int *)shmdata;buffer = shmdata + size

23、of(int);printf("Client operational: shm id is %d, sem id is %dn", shmid, semid); while(1)char input3;printf("nnMenun1.send a messagen");printf("2.Exitn");fgets(input, sizeof(input), stdin);switch(input0)case '1': clientwrite(shmid, semid, buffer);break;case '

24、;2': exit(0);break;void delete(void)printf("nMaster exiting; deleting semaphore %d.n", deleteSemid); if (semctl(deleteSemid, 0, IPC_RMID, 0) = -1 )printf("Error releasing semaphore.n");void sigdelete(int signum)exit(0);void locksem(int semid, int semnum)struct sembuf sb;sb.se

25、m_num = semnum;sb.sem_op = -1;sb.sem_flg = SEM_UNDO;safesemop(semid, &sb, 1);void unlocksem(int semid, int semnum)struct sembuf sb;sb.sem_num = semnum;sb.sem_op = 1;sb.sem_flg = SEM_UNDO;safesemop(semid, &sb, 1);void waitzero(int semid, int semnum)struct sembuf sb;sb.sem_num = semnum;sb.sem_

26、op = 0;sb.sem_flg = 0;safesemop(semid, &sb, 1);void clientwrite(int shmid, int semid, char *buffer)printf("Waiting until empty.");fflush(stdout);locksem(semid, SN_EMPTY);printf("done.n");printf("Enter Message: ");fgets(buffer, BUFFERSIZE, stdin);unlocksem(semid, SN_

27、FULL);int safesemget(key_t key, int nsems, int semflg)int retval;if ( (retval=semget(key, nsems, semflg) = -1)printf("semget error: %s.n", strerror(errno); exit(254);return retval;int safesemctl(int semid, int semnum, int cmd, union semun arg) int retval;if ( (retval=semctl(semid, semnum, cmd, arg) = -1) printf("semctl error: %s.n", strerror(errno); exit(254);return retval;int safe

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論