路由器做網(wǎng)站主機(jī)要備案嗎外鏈網(wǎng)
每個(gè)進(jìn)程的用戶空間都是獨(dú)立的,不能相互訪問。
所有進(jìn)程的內(nèi)核空間(32位系統(tǒng)3G-4G)都是共享的
應(yīng)用場景
- 作為緩沖區(qū),處理速度不同的進(jìn)程之間的數(shù)據(jù)傳輸
- 資源共享:多個(gè)進(jìn)程之間共享同樣的資源,一個(gè)進(jìn)程對(duì)共享數(shù)據(jù)的修改,別的進(jìn)程應(yīng)該立刻看到
- 數(shù)據(jù)傳輸: 一個(gè)進(jìn)程需要將它的數(shù)據(jù)發(fā)送給另一個(gè)進(jìn)程,發(fā)送的數(shù)據(jù)量在一個(gè)字節(jié)到幾兆字節(jié)之間
- 通知事件:一個(gè)進(jìn)程需要向另一個(gè)或一組進(jìn)程發(fā)送消息,通知它(它們)發(fā)生了某種事件(如進(jìn)程終止時(shí)要通知父進(jìn)程)
- 進(jìn)程控制:有些進(jìn)程希望完全控制另一個(gè)進(jìn)程的執(zhí)行(如Debug進(jìn)程),此時(shí)控制進(jìn)程希望能夠攔截另一個(gè)進(jìn)程的所有陷入和異常,并能夠及時(shí)知道它的狀態(tài)改變。
一、管道
缺點(diǎn):緩存區(qū)在內(nèi)核中大小受限,只能承載無格式字節(jié)流;單向通信方式,低效,不適合頻繁交換數(shù)據(jù)
生命周期隨著進(jìn)程創(chuàng)建而建立,隨著進(jìn)程終止而消失
遵循先進(jìn)先出原則,不支持 lseek 之類的文件定位操作
需要雙方通信時(shí),需要建立起兩個(gè)管道
讀端不讀或者讀的慢,寫端要等待讀端;
讀端關(guān)閉,寫端收到SIGPIPE信號(hào)直接終止;
寫端不寫或者寫的慢,讀端要等待寫端;
寫端關(guān)閉,讀端讀完pipe內(nèi)部的數(shù)據(jù)然后再讀,會(huì)讀到0為止,表明讀到文件結(jié)尾;
匿名
管道 pipe
特殊文件只存在于內(nèi)存,沒有存在于文件系統(tǒng)中
只能用于有親緣關(guān)系的進(jìn)程間
shell 命令中的豎線就是匿名管道
pipe() 和 fork() 搭配
有名
管道 fifo
mkfifo myfifo #在文件系統(tǒng)中創(chuàng)建一個(gè)類型為 p 的設(shè)備文件
int mkfifo(const char *pathname, mode_t mode); //默認(rèn)在當(dāng)前的路徑下創(chuàng)建
mkfifo("myfifo", 0666);
open("myfifo", O_RDONLY);
open(MY_FIFO, O_WRONLY);
二、System V 進(jìn)程間通信(操作系統(tǒng)層面上進(jìn)程間通信方案)
消息隊(duì)列
和共享內(nèi)存
是以傳輸數(shù)據(jù)為目的
信號(hào)量
是為了保證進(jìn)程間的同步與互斥而設(shè)計(jì)的
-
消息隊(duì)列
是消息的鏈表,存放在內(nèi)核中并由消息隊(duì)列標(biāo)識(shí)符標(biāo)識(shí),
缺點(diǎn):通信不及時(shí);有大小限制,在內(nèi)核中一條消息最大長度MSGMAX 和一個(gè)隊(duì)列的最大長度MSGMNB(以字節(jié)為單位),
不適合比較大數(shù)據(jù)的傳輸;用戶態(tài)與內(nèi)核態(tài)之間的數(shù)據(jù)拷貝開銷 -
共享內(nèi)存
–最快的IPC
映射一段能被其它進(jìn)程訪問的內(nèi)存,這段共享內(nèi)存由一個(gè)進(jìn)程創(chuàng)建,多個(gè)進(jìn)程均能訪問
帶來新的問題:多進(jìn)程間競爭共享資源,常與信號(hào)量
配合使用
生命周期是隨內(nèi)核的,進(jìn)程要主動(dòng)刪除其創(chuàng)建的共享內(nèi)存:ipcrm -m {shmid}
共享內(nèi)存塊的大小都必須是系統(tǒng)頁面大小的整數(shù)倍。系統(tǒng)頁面大小指的是系統(tǒng)中單個(gè)內(nèi)存頁面包含的字節(jié)數(shù)。在 Linux 系統(tǒng)中,內(nèi)存頁面大小是4KB,不過您仍然應(yīng)該通過調(diào)用 getpagesize 獲取這個(gè)值(通過man 2 getpagesize查看 )
#include <sys/ipc.h>
#include <sys/shm.h> // shmget
#include <sys/types.h> // key_t
// key_t ftok(const char *pathname, int proj_id); //獲取key值
// int shmget(key_t key, size_t size, int shmflg); //得到共享內(nèi)存標(biāo)識(shí)符,不存在時(shí)創(chuàng)建并返回
// void* shmat(int shmid, const void *shmaddr, int shmflg); //共享內(nèi)存綁定到當(dāng)前進(jìn)程的地址空間中
// int shmdt(const void *shmaddr); //取消共享內(nèi)存與進(jìn)程地址空間之間的關(guān)聯(lián)
// int shmctl(int shmid, int cmd, struct shmid_ds *buf); //cmd表示具體控制動(dòng)作:IPC_STAT,IPC_SET改變狀態(tài),IPC_RMID 刪除key_t key = ftok(PATH_NAME, PROJ_ID);//獲取key值
shmid = shmget(key, SIZE, IPC_CREAT | IPC_EXCL); //操作系統(tǒng)給用戶返回的id// ipcs命令查看有關(guān)進(jìn)程間通信設(shè)施的信息
// -q:列出消息隊(duì)列相關(guān)信息。
// -m:列出共享內(nèi)存相關(guān)信息。
// -s:列出信號(hào)量相關(guān)信息
信號(hào)量
一個(gè)整型的計(jì)數(shù)器表示資源的數(shù)量。兩原子操作
P 操作: 把信號(hào)量 -1。相減后信號(hào)量 >= 0,表明還有資源可使用,進(jìn)程可正常繼續(xù)執(zhí)行,否則進(jìn)程需阻塞等待
V 操作: 把信號(hào)量 +1。相減后信號(hào)量 > 0,表明當(dāng)前沒有阻塞中的進(jìn)程;否則表明當(dāng)前有阻塞中的進(jìn)程,將該進(jìn)程喚醒運(yùn)行
信號(hào):用于通知接收進(jìn)程某個(gè)事件已經(jīng)發(fā)生,唯一的異步通信機(jī)制。缺點(diǎn):傳遞信息少
信號(hào)事件來源主要: 硬件來源(如鍵盤 Cltr+C )和 軟件來源(如 kill 命令)
可以在任何時(shí)候發(fā)送信號(hào)給某一進(jìn)程,一旦有信號(hào)產(chǎn)生,進(jìn)程就對(duì)信號(hào)處理(執(zhí)行默認(rèn)操作,定義一個(gè)信號(hào)處理函數(shù),忽略信號(hào))
# Ctrl+C 產(chǎn)生 SIGINT 信號(hào),表示終止該進(jìn)程;
# SIGTERM 終止該進(jìn)程;通過 Core Dump 將當(dāng)前進(jìn)程的運(yùn)行狀態(tài)保存在文件里面,方便事后分析問題在哪里
# Ctrl+Z 產(chǎn)生 SIGTSTP 信號(hào),表示停止該進(jìn)程,但還未結(jié)束;
kill -l1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7
58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX
套接字
:3個(gè)屬性:域、類型、協(xié)議。唯一的跨網(wǎng)絡(luò)主機(jī)的通信機(jī)制
// domain: AF_INET 用于 IPV4、
// AF_INET6 用于 IPV6
// AF_LOCAL/AF_UNIX 二者等價(jià),用于本機(jī)
// type: SOCK_STREAM 字節(jié)流,對(duì)應(yīng) TCP
// SOCK_DGRAM 數(shù)據(jù)報(bào),對(duì)應(yīng) UDP
// SOCK_RAW 原始套接字
int socket(int domain, int type, int protocal);
TCP 服務(wù)端負(fù)責(zé)監(jiān)聽的 socket 叫作監(jiān)聽 socket ==> listen_fd
調(diào)用 accept 時(shí),連接成功,會(huì)返回一個(gè)已完成連接的 socket,叫作已完成連接 socket ==> sock_fd,用來后續(xù)傳輸數(shù)據(jù)。
是「兩個(gè)」 不同 socket
UDP 是沒有連接的,所以不需要三次握手。不存在客戶端和服務(wù)端的概念
每次通信時(shí),調(diào)用 sendto 和 recvfrom,都要傳入目標(biāo)主機(jī)的 IP 地址和端口
本地 socket 的實(shí)現(xiàn)效率大大高于 IPv4 和 IPv6 的字節(jié)流、數(shù)據(jù)報(bào) socket 實(shí)現(xiàn)
不像 TCP 和 UDP 要綁定 IP 地址和端口,而是綁定一個(gè)本地文件
三、POSIX 進(jìn)程間通信:共享內(nèi)存、消息隊(duì)列、信號(hào)量、
參考:https://www.cnblogs.com/tongh/p/18002994
Linux內(nèi)核v2.6.6和glibc2.3.4之后的版本支持POSIX消息隊(duì)列 (ldd --version)
POSIX:可移植操作系統(tǒng)接口,是IEEE為要在各種UNIX操作系統(tǒng)上運(yùn)行的軟件而定義的一系列API標(biāo)準(zhǔn)的總稱,其正式稱呼為IEEE 1003,而國際標(biāo)準(zhǔn)名稱為ISO/IEC 9945
標(biāo)準(zhǔn)線上地址:注冊后可以在線閱讀或者下載。
IEEE和Open Group 的POSIX認(rèn)證
相關(guān)頁面
20世紀(jì)80年代中期,Unix廠商試圖通過加入新的、往往不兼容的特性來使它們的程序與眾不同。局面非常混亂,麻煩也就隨之而來了。為了提高兼容性和應(yīng)用程序的可移植性,阻止這種趨勢, IEEE(電氣和電子工程師協(xié)會(huì))開始努力標(biāo)準(zhǔn)化Unix的開發(fā),后來由 Richard Stallman命名為“Posix”。
這套標(biāo)準(zhǔn)涵蓋了很多方面,比如Unix系統(tǒng)調(diào)用的C語言接口、shell程序和工具、線程及網(wǎng)絡(luò)編程
有了這個(gè)規(guī)范,就可以調(diào)用通用的API
消息隊(duì)列
-
優(yōu)點(diǎn)
靈活,支持多種數(shù)據(jù)類型和優(yōu)先級(jí)。
可靠,消息持久化且不會(huì)因發(fā)送者崩潰而丟失。
高效,支持大量數(shù)據(jù)的傳輸和并行處理 -
缺點(diǎn)
數(shù)據(jù)復(fù)制的開銷。
需要管理訪問權(quán)限以確保安全性。
-
#include <fcntl.h>
#include <sys/stat.h>
#include <mqueue.h>mqd_t mq_open(const char *name, int oflag, ...); //打開一個(gè)已存在的消息隊(duì)列,或創(chuàng)建一個(gè)新的消息隊(duì)列
//發(fā)送消息
int mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msg_prio);
int mq_timedsend(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msg_prio, const struct timespec *abs_timeout);//接收消息
ssize_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio);
ssize_t mq_timedreceive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio, const struct timespec *abs_timeout);//設(shè)置/獲取消息隊(duì)列的屬性
int mq_getattr(mqd_t mqdes, struct mq_attr *mqstat);
int mq_setattr(mqd_t mqdes, const struct mq_attr *mqstat, struct mq_attr *omqstat);int mq_close(mqd_t mqdes); //關(guān)閉
int mq_unlink(const char *name); //刪除一個(gè)命名的消息隊(duì)列。
共享內(nèi)存
#include <sys/mman.h>
#include <sys/stat.h> /* For mode constants */
#include <fcntl.h> /* For O_* constants */int shm_open(const char *name, int oflag, mode_t mode); //創(chuàng)建或打開一個(gè)POSIX共享內(nèi)存對(duì)象
int ftruncate(int fd, off_t length); //設(shè)置大小
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); //映射到進(jìn)程的地址空間
int munmap(void *addr, size_t length); //解除映射
int shm_unlink(const char *name); //刪除共享內(nèi)存對(duì)象
信號(hào)量
有名信號(hào)量:操作系統(tǒng)內(nèi)核維護(hù)的具有全局唯一名字的信號(hào)量
無名信號(hào)量是一種不具有全局唯一名字的信號(hào)量,通常只能在相關(guān)的進(jìn)程或線程之間進(jìn)行共享
只有0和1兩種取值的信號(hào)量叫做二進(jìn)制信號(hào)量
#include <fcntl.h>
#include <sys/stat.h>
#include <semaphore.h>sem_t *sem_open(const char *name, int oflag, mode_t mode, unsigned int value); //創(chuàng)建或打開有名信號(hào)量
int sem_init(sem_t *sem, int pshared, unsigned int value); //初始化無名信號(hào)量int sem_getvalue(sem_t *sem, int *sval); //獲取當(dāng)前信號(hào)量的值
int sem_post(sem_t *sem); //V操作:信號(hào)量 +1
int sem_wait(sem_t *sem); //等待信號(hào)量減小。如果信號(hào)量的值大于0,則將其減小1并立即返回,否則會(huì)阻塞當(dāng)前線程直到信號(hào)量變?yōu)榇笥?為止
int sem_trywait(sem_t *sem); //嘗試等待信號(hào)量減小的非阻塞版本。如果信號(hào)量的值大于0,則將其減小1并立即返回,否則會(huì)立即返回,并且不會(huì)阻塞當(dāng)前線程
int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout); //函數(shù)允許設(shè)置一個(gè)超時(shí)時(shí)間,如果在指定的時(shí)間內(nèi)未能獲得信號(hào)量,函數(shù)將返回一個(gè)特定的錯(cuò)誤碼int sem_close(sem_t *sem); //關(guān)閉有名信號(hào)量
int sem_destroy(sem_t *sem); //銷毀無名信號(hào)量
int sem_unlink(const char *name); //從系統(tǒng)中刪除有名信號(hào)量