日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

进程间通信(总结)

發(fā)布時(shí)間:2024/3/13 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 进程间通信(总结) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

轉(zhuǎn)自:http://blog.sina.com.cn/s/blog_726c4bd20100ryan.html


信號(hào)

進(jìn)程間通信的方法有: 信號(hào)、文件鎖、管道、FIFO、信號(hào)量、共享內(nèi)存、消息隊(duì)列
最有效,最快的方法是:共享內(nèi)存
信號(hào)量、共享內(nèi)存、消息隊(duì)列是system V IPC
必須要求是親屬進(jìn)程間才能通信的方法是:管道
?
信號(hào)機(jī)制:
收到信號(hào)后是異步運(yùn)行的。
信號(hào)(signal)機(jī)制是Linux系統(tǒng)中最為古老的進(jìn)程之間的通信機(jī)制
信號(hào)事件的發(fā)生有兩個(gè)來源:
硬件來源,比如我們按下了鍵盤或者其它硬件故障;
軟件來源,最常用發(fā)送信號(hào)的系統(tǒng)函數(shù)是kill(), raise(), alarm()和setitimer()等函數(shù),軟件來源還包括一些非法運(yùn)算等操作。
? ? ? ? ?kill()函數(shù)可以對(duì)任何進(jìn)程發(fā)送信號(hào),raise()只能對(duì)自己發(fā)信號(hào),alarm()和setitimer()發(fā)送定時(shí)信號(hào)。
? ? ? ? ?可以用kill ?-l 命令列出所有的信號(hào)。
? ? ? ? ?程序在休眠時(shí)搜索不到信息。
? ? ? ? ?信息未處理完成時(shí),系統(tǒng)無法運(yùn)行。
進(jìn)程對(duì)信號(hào)的處理
v ? ? ? 進(jìn)程可以通過三種方式來響應(yīng)和處理一個(gè)信號(hào):
忽略信號(hào)、捕捉信號(hào)、執(zhí)行缺省操作
但有兩個(gè)信號(hào)不能忽略:SIGKILL 和SIGSTOP
信號(hào)處理函數(shù)的安裝
#include<signal.h>
void( *signal(int sig, void( *func)(int)))(int);
? ? ? ? ?int sigaction(int ?signum,const struct sigacton *act,struct sigaction *oldact);
? ? ? ? ?其中:signal()在可靠的信號(hào)系統(tǒng)調(diào)用的基礎(chǔ)上實(shí)現(xiàn),是庫函數(shù)。它只是兩個(gè)參數(shù),不支持信號(hào)傳遞信息。第一個(gè)參數(shù)是要安裝的信號(hào)量,第二個(gè)參數(shù)是對(duì)第一個(gè)參數(shù)指定的信號(hào)的處理。
如果func不是函數(shù)指針,必須是下列兩個(gè)宏:
SIG_IGN:忽略信號(hào)。
SIG_DEF:采用系統(tǒng)默認(rèn)的方式處理信號(hào),執(zhí)行缺省操作。
返回值:返回先前的信號(hào)處理函數(shù)指針,如果有錯(cuò)誤則返回-1。
?
信號(hào)的發(fā)送
除了內(nèi)核和超級(jí)用戶,并不是每個(gè)進(jìn)程都可以向其他的進(jìn)程發(fā)送信號(hào)。
一般的進(jìn)程只能向具有相同uid和gid的進(jìn)程發(fā)送信號(hào),或向相同進(jìn)程組中的其他進(jìn)程發(fā)送信號(hào)。
常用的發(fā)送信號(hào)的函數(shù)有kill()、raise ()、alarm()、setitimer()、abort() 等。
?
kill()函數(shù):給指定的進(jìn)程發(fā)送某一個(gè)信號(hào)
#include <sys/types.h>
#include <signal.h>
?int kill(pid_t pid, int sig);
pid>0 ?給PID為pid的進(jìn)程發(fā)送信號(hào)
pid=0 ?給同一個(gè)進(jìn)程組的所有進(jìn)程發(fā)送信號(hào)
pid<0 且 pid!=-1 ?給進(jìn)程組ID為-pid的所有進(jìn)程發(fā)送信號(hào)
pid=-1 ?給出了自身之外的PID大于1的進(jìn)程發(fā)送信號(hào)
第二個(gè)參數(shù)是要發(fā)送的信號(hào)值,當(dāng)?shù)诙€(gè)參數(shù)為0的時(shí)候,實(shí)際上不會(huì)發(fā)送任何信號(hào)
返回值:成功為0;失敗返回-1。
EINVAL:所發(fā)送的信號(hào)無效
EPERM:沒有向目標(biāo)進(jìn)程發(fā)送信號(hào)的權(quán)限
ESRCH:目標(biāo)進(jìn)程不存在或者進(jìn)程已經(jīng)終止,處于僵尸。
raise()函數(shù):給進(jìn)程本身發(fā)送一個(gè)信號(hào)
? ? #include <signal.h>
? ? int raise(int sig); ?(給自己發(fā)信號(hào))
相當(dāng)于kill(getpid(),sig);
返回值:成功為0;失敗返回-1
alarm()函數(shù):是一個(gè)簡(jiǎn)單定時(shí)器,專為SIGALRM信號(hào)設(shè)計(jì)
#include <unistd.h>
unsigned int alarm(unsigned int seconds);
在指定的seconds秒之后,給進(jìn)程本身發(fā)生一個(gè)SIGALRM信號(hào)
?
setitimer()功能強(qiáng)大更強(qiáng)大的定時(shí)器函數(shù),支持3種類型的定時(shí)器,但是從本質(zhì)上,它是和alarm共享同一個(gè)進(jìn)程內(nèi)的定時(shí)器
#include <sys/time.h>
int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue);?
abort():向進(jìn)程發(fā)送SIGABORT信號(hào),默認(rèn)情況下進(jìn)程會(huì)異常退出
?
文件鎖
當(dāng)多個(gè)進(jìn)程都需要對(duì)同一個(gè)文件進(jìn)行讀寫操作的時(shí)候,有時(shí)候需要確保進(jìn)程在一次讀寫操作完成之前,文件不被其他進(jìn)程修改。文件鎖機(jī)制提供了這樣的同步功能。
int fcntl(int fd, int cmd, struct flock *lock);
fd 文件描述符
cmd參數(shù):F_GETLK:獲取文件鎖當(dāng)前的狀態(tài)。
F_SETLK:設(shè)置文件鎖。
F_SETLKW:這是F_SETLK的阻塞版本,如果新加的鎖被拒絕,那么進(jìn)程被阻塞直到可以加鎖。
struct flock{
? ? ? ? …
? ? ? ? ?short l_type; ? ? ? ? ??
? ? ? ? ?short l_whence; ? ? ? ??
? ? ? ? ?off_t l_start; ? ? ? ? ? ? ?
? ? ? ? ?off_t l_len; ? ? ? ? ? ?
? ? ? ? ?…};
l_type類型:
F_RDLCK:讀鎖
F_WRLCK:寫鎖
F_UNLCK:解鎖
為了鎖定整個(gè)文件,通常的方法是將l_start指定為0,l_whence指定為SEEK_SEK, l_len指定為0。
?
管道
?
管道是針對(duì)于本地計(jì)算機(jī)的兩個(gè)進(jìn)程之間的通信而設(shè)計(jì)的通信方法,管道建立后,實(shí)際獲得兩個(gè)文件描述符:一個(gè)用于讀取而另外一個(gè)用于寫入。
管道是半雙工的,數(shù)據(jù)只能向一個(gè)方向流動(dòng),需要雙方通信時(shí),需要建立起兩個(gè)管道。
只能用于父子進(jìn)程或者兄弟進(jìn)程之間(具有親緣關(guān)心的進(jìn)程)。
單獨(dú)構(gòu)成一種獨(dú)立的文件系統(tǒng):管道對(duì)于管道兩端的進(jìn)程而言,就是一個(gè)文件,但它不是普通的文件,它不屬于某種文件系統(tǒng),而是單獨(dú)構(gòu)成一種文件系統(tǒng),并且只存在于內(nèi)存中。
數(shù)據(jù)的讀出和寫入:一個(gè)進(jìn)程向管道中寫的內(nèi)容被管道另一端的進(jìn)程讀出。寫入的內(nèi)容每次都添加在管道緩沖區(qū)的末尾,并且每次都是從緩沖區(qū)的頭部讀出數(shù)據(jù)。
?
管道的創(chuàng)建
系統(tǒng)調(diào)用pipe()用于創(chuàng)建一個(gè)管道
int pipe(int filedes[2]);
建立管道: ?
filedes[0]: 為pipe的讀出端
filedes[1]: 為pipe的寫入端
兩個(gè)文件描述符數(shù)組。
?
FIFO
FIFO不同于管道之處在于它提供一個(gè)路徑名與之關(guān)聯(lián),以FIFO的文件形式存在于文件系統(tǒng)中
在文件系統(tǒng)中是一個(gè)有名字的管道
任何進(jìn)程都可以打開
進(jìn)程間無需關(guān)聯(lián)
注:直接映射到磁盤上,有文件名,故任何進(jìn)程都可以打開。
FIFO的創(chuàng)建
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
?
信號(hào)量
System IPC中,對(duì)于每一個(gè)新建的信號(hào)量、消息隊(duì)列以及共享內(nèi)存,都有一個(gè)在整個(gè)系統(tǒng)中唯一的標(biāo)識(shí)符。每個(gè)標(biāo)識(shí)符也都有唯一對(duì)應(yīng)的關(guān)鍵字,關(guān)鍵字的數(shù)據(jù)類型由系統(tǒng)定義為key_t。
創(chuàng)建/獲取信號(hào)量
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semget(key_t key, int nsems, int semflg);
Key:鍵值
1. 指定鍵值
2. IPC_PRIVATE
系統(tǒng)指定鍵值
nsems:信號(hào)量的數(shù)目
信號(hào)量集合的數(shù)目
Smeflg:信號(hào)量標(biāo)志
1.IPC_CREATE 如果內(nèi)核中沒有此隊(duì)列,則創(chuàng)建它。
2.IPC_EXECL ? ? 當(dāng)和IPC_CREAT一起使用時(shí),如果隊(duì)列已經(jīng)存在,則返回錯(cuò)誤。
3.mode_flags: ? ? ? 類似于文件的權(quán)限
?
信號(hào)量操作
當(dāng)進(jìn)程需要申請(qǐng)或者釋放公共資源的時(shí)候,可以調(diào)用semop()來對(duì)信號(hào)量進(jìn)行操作
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semop(int semid, struct sembuf *sops, unsigned nsops);
sops:指向sembuf結(jié)構(gòu)的數(shù)組指針
unsigned short sem_num:組中包含的信號(hào)量數(shù)量
short ?sem_op:操作類型的整數(shù)
整數(shù):加到信號(hào)量的值上
負(fù)數(shù):信號(hào)量的值減去絕對(duì)值,如果小于零,進(jìn)程阻塞,直到信號(hào)量的值至少等于其絕對(duì)值
0:導(dǎo)致操作阻塞,直到信號(hào)量的值為0才繼續(xù)。
?
short ?sem_flg:一個(gè)符號(hào)位
IPC_NOWAIT: 非阻塞操作
SEM_UNDO:linux會(huì)在進(jìn)程退出的時(shí)候自動(dòng)撤銷該次操作。
?
信號(hào)量控制
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semctl(int semid, int semnum, int cmd, ...);
第一個(gè)參數(shù)semid指定信號(hào)量集,第二個(gè)參數(shù)semnum指定了讀信號(hào)量集里面的哪一個(gè)信號(hào)集進(jìn)行操作(編號(hào)),第三個(gè)參數(shù)cmd指定具體的操作類型(指令)。
當(dāng)進(jìn)程創(chuàng)建了新的信號(hào)量集的時(shí)候,調(diào)用了atexit(&sem_delete)函數(shù),使得程序退出時(shí),信號(hào)量集被釋放。
?
消息隊(duì)列
消息隊(duì)列是系統(tǒng)內(nèi)核地址空間中的一個(gè)內(nèi)部的鏈表。消息可以按照順序發(fā)送到隊(duì)列中,也可以以幾種不同的方式從隊(duì)列中讀取。每一個(gè)消息隊(duì)列用一個(gè)唯一的IPC標(biāo)識(shí)符表示
Msgbuf數(shù)據(jù)結(jié)構(gòu)
struct msgbuf {
? ? ? ?long mtype; ? ? ??
? ? ? ?char mtext[1]; ? ? ?
};
mtype指消息的類型,它由一個(gè)整數(shù)來代表,并且它只能是大于0的整數(shù)。
mtext是消息數(shù)據(jù)本身
?
創(chuàng)建消息隊(duì)列
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h> ??
int msgget(key_t key, int msgflg);
Key:鍵值
1. 指定鍵值(可有ftok()函數(shù)獲得)
2. IPC_PRIVATE ?系統(tǒng)指定鍵值
msgflg :信號(hào)量標(biāo)志
1.IPC_CREATE ?如果內(nèi)核中沒有此隊(duì)列,則創(chuàng)建它。
2.IPC_EXECL ? 當(dāng)和IPC_CREAT一起使用時(shí),如果隊(duì)列已經(jīng)存在,則返回錯(cuò)誤。
3.mode_flags:類似于文件的權(quán)限
發(fā)送和接收消息
msgsnd()系統(tǒng)調(diào)用用于向隊(duì)列發(fā)送一條消息:
int msgsnd(int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg);
msgrcv()系統(tǒng)調(diào)用用于從消息隊(duì)列讀取一條消息:
ssize_t msgrcv(int msqid, struct msgbuf *msgp, size_t msgsz, long msgtyp, int msgflg);
如果msgtype=0,接收隊(duì)列的第一個(gè)消息(按時(shí)間順序依次收到一個(gè)消息),大于0接收隊(duì)列中消息類型等于這個(gè)值的第一個(gè)消息(特定值的消息),小于0接收消息隊(duì)列中小于或等于msgtype絕對(duì)值的所有消息中的最小一個(gè)消息(按編號(hào)順序依次收消息)
?
消息隊(duì)列的控制
通過msgctl()可以對(duì)消息隊(duì)列進(jìn)行控制或者一些屬性的修改:
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
cmd:消息隊(duì)列的操作
IPC_STAT:讀取消息隊(duì)列的數(shù)據(jù)結(jié)構(gòu)msqid_ds,并將其存儲(chǔ)在buf指定的地址中。
IPC_SET:設(shè)置消息隊(duì)列的數(shù)據(jù)結(jié)構(gòu)msqid_ds中的ipc_perm、msg_qbytes、msg_ctime元素的值。這個(gè)值取自buf參數(shù)。 ?
IPC_RMID:從系統(tǒng)內(nèi)核中移走消息隊(duì)列。
msgid_ds結(jié)構(gòu)體
struct msqid_ds{
? struct ipc_perm msg_perm; ? ??
? time_t ? ? ? ? ?msg_stime; ? ?
? time_t ? ? ? ? ?msg_rtime; ? ?
? time_t ? ? ? ? ?msg_ctime; ? ?
? unsigned long ? __msg_cbytes;?
? msgqnum_t ? ? ? msg_qnum; ? ??
? msglen_t ? ? ? ?msg_qbytes; ??
? pid_t ? ? ? ? ? msg_lspid; ? ?
? pid_t ? ? ? ? ? msg_lrpid; ? ?
}
共享內(nèi)存
兩個(gè)不同進(jìn)程A、B共享內(nèi)存的基本原理是,同一塊物理內(nèi)存被映射到進(jìn)程A、B各自的進(jìn)程地址空間。進(jìn)程A可以即時(shí)看到進(jìn)程B對(duì)共享內(nèi)存中數(shù)據(jù)的更新,反之亦然。
?
創(chuàng)建和獲取共享內(nèi)存
系統(tǒng)調(diào)用shmget()用于創(chuàng)建共享內(nèi)存或者獲取一個(gè)已經(jīng)存在的共享內(nèi)存的標(biāo)識(shí)符:
int shmget(key_t key, size_t size, int shmflg);
key:鍵值
1. 指定鍵值
2. IPC_PRIVATE ?系統(tǒng)指定鍵值
size:共享內(nèi)存大小
msgflg :共享內(nèi)存標(biāo)志
1.IPC_CREATE ?如果內(nèi)核中沒有此隊(duì)列,則創(chuàng)建它。
2.IPC_EXECL ? 當(dāng)和IPC_CREAT一起使用時(shí),如果隊(duì)列已經(jīng)存在,則返回錯(cuò)誤。
3.mode_flags: ? 類似于文件的權(quán)限
?
?
系統(tǒng)調(diào)用shmat()可以獲取一個(gè)共享內(nèi)存的地址,并將其連接到進(jìn)程中:
void *shmat(int shmid, const void *shmaddr, int shmflg);
shmid:
由shmget返回的共享內(nèi)存標(biāo)志
shmaddr:
映射該共享內(nèi)存塊的進(jìn)程內(nèi)存地址
如果為NULL,Linux將自動(dòng)選擇合適的地址
shmflg:
SHM_RND
SHM_RDONLY
?
通過shmctl()可以對(duì)消息隊(duì)列進(jìn)行控制或者一些屬性的修改:
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
cmd:共享內(nèi)存的操作
IPC_STAT:讀取一個(gè)共享內(nèi)存的數(shù)據(jù)結(jié)構(gòu)shmid_ds,并將其存儲(chǔ)在buf指定的地址中。
IPC_SET:設(shè)置消息隊(duì)列的數(shù)據(jù)結(jié)構(gòu)shmid_ds中各個(gè)元素的值。這個(gè)值取自buf參數(shù)。
IPC_RMID:把共亨內(nèi)存標(biāo)記為可刪除,當(dāng)最后一個(gè)進(jìn)程脫連此共享內(nèi)存的時(shí)候,系統(tǒng)將刪除該共享內(nèi)存

總結(jié)

以上是生活随笔為你收集整理的进程间通信(总结)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。