linux進程間通信——深入理解linux信號量

2020-08-28 linux技術棧

信號燈

信號燈與其他進程間通信方式不大相同,它主要提供對進程間共享資源訪問控制機制。相當於內存中的標誌,進程可以根據它判定是否能夠訪問某些共享資源(臨界區,類似於互斥鎖),同時,進程也可以修改該標誌。除了用於訪問控制外,還可用於進程同步。

1. 信號燈概述

信號燈與其他進程間通信方式不大相同,它主要提供對進程間共享資源訪問控制機制。相當於內存中的標誌,進程可以根據它判定是否能夠訪問某些共享資源(臨界區,類似於互斥鎖),同時,進程也可以修改該標誌。除了用於訪問控制外,還可用於進程同步。信號燈有以下兩種類型:

  • 二值信號燈:最簡單的信號燈形式,信號燈的值只能取0或1,類似於互斥鎖。
    註:二值信號燈能夠實現互斥鎖的功能,但兩者的關注內容不同。信號燈強調共享資源,只要共享資源可用,其他進程同樣可以修改信號燈的值;互斥鎖更強調進程,佔用資源的進程使用完資源後,必須由進程本身來解鎖。
  • 計算信號燈:信號燈的值可以取任意非負值(當然受內核本身的約束)。

2. Linux信號燈

linux對信號燈的支持狀況與消息隊列一樣,在red had 8.0發行版本中支持的是系統V的信號燈。因此,本文將主要介紹系統V信號燈及其相應API。在沒有聲明的情況下,以下討論中指的都是系統V信號燈。

注意,通常所說的系統V信號燈指的是計數信號燈集。

3. 信號燈與內核

1、系統V信號燈是隨內核持續的,只有在內核重起或者顯示刪除一個信號燈集時,該信號燈集才會真正被刪除。因此系統中記錄信號燈的數據結構(struct ipc_ids sem_ids)位於內核中,系統中的所有信號燈都可以在結構sem_ids中找到訪問入口。

2、下圖說明了內核與信號燈是怎樣建立起聯繫的:

其中:structipc_ids sem_ids是內核中記錄信號燈的全局數據結構;描述一個具體的信號燈及其相關信息。

其中,struct sem結構如下:

struct sem{ int semval; // current value int sempid; // pid of last operation}

從上圖可以看出,全局數據結構struct ipc_ids sem_ids可以訪問到struct ipc_id ipcid的一個成員:struct kern_ipc_perm;而每個struct kern_ipc_perm能夠與具體的信號燈集對應起來是因為在該結構中,有一個key_t類型成員key,而key則唯一確定一個信號燈集struct sem_array;同時,結構struct sem_array的最後一個成員sem_nsems確定了該信號燈在信號燈集中的順序,這樣內核就能夠記錄每個信號燈的信息了。

kern_ipc_perm結構如下:

//內核中全局數據結構sem_ids能夠訪問到該結構;struct kern_ipc_perm{ key_t key; //該鍵值則唯一對應一個信號燈集 uid_t uid; gid_t gid; uid_t cuid; gid_t cgid; mode_t mode; unsigned long seq;}

/*系統中的每個信號燈集對應一個sem_array 結構 */struct sem_array { struct kern_ipc_perm sem_perm; /* permissions .. see ipc.h */ time_t sem_otime; /* last semop time */ time_t sem_ctime; /* last change time */ struct sem *sem_base; /* ptr to first semaphore in array */ struct sem_queue *sem_pending; /* pending operations to be processed */ struct sem_queue **sem_pending_last; /* last pending operation */ struct sem_undo *undo; /* undo requests on this array */ unsigned long sem_nsems; /* no. of semaphores in array */};

其中,sem_queue結構如下:

/* 系統中每個因為信號燈而睡眠的進程,都對應一個sem_queue結構*/struct sem_queue { struct sem_queue * next; /* next entry in the queue */ struct sem_queue ** prev; /* previous entry in the queue, *(q->prev) == q */ struct task_struct* sleeper; /* this process */ struct sem_undo * undo; /* undo structure */ int pid; /* process id of requesting process */ int status; /* completion status of operation */ struct sem_array * sma; /* semaphore array for operations */ int id; /* internal sem id */ struct sembuf * sops; /* array of pending operations */ int nsops; /* number of operations */ int alter; /* operation will alter semaphore */};

需要C/C++ Linux伺服器架構師學習資料私信「資料」(資料包括C/C++,Linux,golang技術,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒體,CDN,P2P,K8S,Docker,TCP/IP,協程,DPDK,ffmpeg等),免費分享

4. 操作信號燈

對信號燈的操作無非有下面三種類型:

1、打開或創建信號燈 與消息隊列的創建及打開基本相同,不再詳述。

2、信號燈值操作 linux可以增加或減小信號燈的值,相應於對共享資源的釋放和佔有。具體參見後面的semop系統調用。

3、獲得或設置信號燈屬性: 系統中的每一個信號燈集都對應一個struct sem_array結構,該結構記錄了信號燈集的各種信息,存在於系統空間。為了設置、獲得該信號燈集的各種信息及屬性,在用戶空間有一個重要的聯合結構與之對應,即union semun。

聯合semun數據結構:

union semun { int val; /* value for SETVAL */ struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */ unsigned short *array; /* array for GETALL & SETALL */ struct seminfo *__buf; /* buffer for IPC_INFO */ //test!! void *__pad; }; The semid_ds data structure is defined in <sys/sem.h> as follows: struct semid_ds { struct ipc_perm sem_perm; /* Ownership and permissions */ time_t sem_otime; /* Last semop time */ time_t sem_ctime; /* Last change time */ unsigned short sem_nsems; /* No. of semaphores in set */}; The ipc_perm structure is defined in <sys/ipc.h> as follows (the highlighted fields are settable using IPC_SET):struct ipc_perm { key_t key; /* Key supplied to semget() */ uid_t uid; /* Effective UID of owner */ gid_t gid; /* Effective GID of owner */ uid_t cuid; /* Effective UID of creator */ gid_t cgid; /* Effective GID of creator */ unsigned short mode; /* Permissions */ unsigned short seq; /* Sequence number */}; seminfo, defined in <sys/sem.h> if the _GNU_SOURCE feature test macro is defined: struct seminfo { int semmap; /* of semaphore sets */ int semmns; /* Max. of undo structures; unused */ int semmsl; /* Max. of operations for semop() */ int semume; /* Max. include <sys/types.h>include <sys/types.h>include <sys/sem.h>

1)int semget(key_t key, int nsems, int semflg) 參數key是一個鍵值,由ftok獲得,唯一標識一個信號燈集,用法與msgget()中的key相同;參數nsems指定打開或者新創建的信號燈集中將包含信號燈的數目;semflg參數是一些標誌位。參數key和semflg的取值,以及何時打開已有信號燈集或者創建一個新的信號燈集與msgget()中的對應部分相同。該調用返回與健值key相對應的信號燈集描述字。 調用返回:成功返回信號燈集描述字,否則返回-1。 註:如果key所代表的信號燈已經存在,且semflg指定了IPC_CREAT|IPC_EXCL標誌,那麼即使參數nsems與原來信號燈的數目不等,返回的也是EEXIST錯誤;如果semflg只指定了IPC_CREAT標誌,那麼參數nsems必須與原來的值一致,在後面程序實例中還要進一步說明。

Upon creation, the least significant 9 bits of the argument semflg define the permissions (for owner, group and others) for the semaphore set. These bits have the same format, and the same meaning, as the mode argument of open(2) (though the execute permissions are not meaningful for semaphores, and write permissions mean permission to alter semaphore values)

例如:IPC_CREAT | 權限標識

2)int semop(int semid, struct sembuf *sops, unsigned nsops); semid是信號燈集ID,sops指向數組的每一個sembuf結構都刻畫一個在特定信號燈上的操作。nsops為sops指向數組的大小。 sembuf結構如下:

struct sembuf{ unsigned short sem_num; /* semaphore index in array */ short sem_op; /* semaphore operation */ short sem_flg; /* operation flags */};


sem_num對應信號集中的信號燈,其值是一個從0到相應的信號量集的資源總數(ipc_perm.sem_nsems)之間的整數,0對應第一個信號燈。

sem_flg可取IPC_NOWAIT以及SEM_UNDO兩個標誌。如果設置了SEM_UNDO標誌,那麼在進程結束時,相應的操作將被取消,這是比較重要的一個標誌位。如果設置了該標誌位,那麼在進程沒有釋放共享資源就退出時,內核將代為釋放。如果為一個信號燈設置了該標誌,內核都要分配一個sem_undo結構來記錄它,為的是確保以後資源能夠安全釋放。事實上,如果進程退出了,那麼它所佔用的資源就釋放了,但信號燈值卻沒有改變,此時,信號燈值反映的已經不是資源佔有的實際情況,在這種情況下,問題的解決就靠內核來完成。這有點像殭屍進程,進程雖然退出了,資源也都釋放了,但內核進程表中仍然有它的記錄,此時就需要父進程調用waitpid來解決問題了。

sem_op的值大於0,等於0以及小於0確定了對sem_num指定的信號燈進行的三種操作。具體請參考linux相應手冊頁。 (是信號量在一次操作中需要改變的數值(可以是非1的數值)。通常只會用到兩個值:-1----P操作,申請資源,如果已經沒有資源可申請,則阻塞。為阻塞原語;1---V操作,釋放資源,為喚醒原語。)

也許從實際含義上更好理解這些操作:信號燈的當前值記錄相應資源目前可用數目;sem_op>0對應相應進程要釋放sem_op數目的共享資源;sem_op=0可以用於對共享資源是否已用完的測試;sem_op<0相當於進程要申請-sem_op個共享資源。再聯想操作的原子性,更不難理解該系統調用何時正常返回,何時睡眠等待。調用返回:成功返回0,否則返回-1。

若sem_op 是正數,其值就加到semval上,即釋放信號量控制的資源若sem_op 是0,那麼調用者希望等到semval變為0,如果semval是0就返回;若sem_op 是負數,那麼調用者希望等待到semval變為大於或等於sem_op的絕對值。如果當前semval大於或等於sem_op的絕對值,則立即返回。

這裡需要強調的是semop同時操作多個信號燈,在實際應用中,對應多種資源的申請或釋放。semop保證操作的原子性,這一點尤為重要。尤其對於多種資源的申請來說,要麼一次性獲得所有資源,要麼放棄申請,要麼在不佔有任何資源情況下繼續等待,這樣,一方面避免了資源的浪費;另一方面,避免了進程之間由於申請共享資源造成死鎖。

3) int semctl(int semid,int semnum,int cmd,union semun arg) 該系統調用實現對信號燈的各種控制操作,參數semid指定信號燈集,參數cmd指定具體的操作類型;參數semnum指定對哪個信號燈操作,只對幾個特殊的cmd操作有意義;arg用於設置或返回信號燈信息。該系統調用詳細信息請參見其手冊頁,這裡只給出參數cmd所能指定的操作。

IPC_RMID Immediately remove the semaphore set, awakening all processes blocked in semop()

calls on the set (with an error return and errno set to EIDRM). The effective user ID

of the calling process must match the creator or owner of the semaphore set, or the

caller must be privileged. The argument semnum is ignored.

調用返回:調用失敗返回-1,成功返回與cmd相關:

5. 信號燈的限制

1、一次系統調用semop可同時操作的信號燈數目SEMOPM,semop中的參數nsops如果超過了這個數目,將返回E2BIG錯誤。SEMOPM的大小特定與系統,redhat 8.0為32。

2、信號燈的最大值:SEMVMX,當設置信號燈值超過這個限制時,會返回ERANGE錯誤。在redhat 8.0中該值為32767。

3、系統範圍內信號燈集的最大數目SEMMNI以及系統範圍內信號燈的最大數目SEMMNS。超過這兩個限制將返回ENOSPC錯誤。redhat 8.0中該值為32000。

4、每個信號燈集中的最大信號燈數目SEMMSL,redhat 8.0中為250。 SEMOPM以及SEMVMX是使用semop調用時應該注意的;SEMMNI以及SEMMNS是調用semget時應該注意的。SEMVMX同時也是semctl調用應該注意的。

6. 競爭問題

第一個創建信號燈的進程同時也初始化信號燈,這樣,系統調用semget包含了兩個步驟:創建信號燈;初始化信號燈。由此可能導致一種競爭狀態:第一個創建信號燈的進程在初始化信號燈時,第二個進程又調用semget,並且發現信號燈已經存在,此時,第二個進程必須具有判斷是否有進程正在對信號燈進行初始化的能力。在參考文獻[1]中,給出了繞過這種競爭狀態的方法:當semget創建一個新的信號燈時,信號燈結構semid_ds的sem_otime成員初始化後的值為0。因此,第二個進程在成功調用semget後,可再次以IPC_STAT命令調用semctl,等待sem_otime變為非0值,此時可判斷該信號燈已經初始化完畢。下圖描述了競爭狀態產生及解決方法:

實際上,這種解決方法也是基於這樣一個假定:第一個創建信號燈的進程必須調用semop,這樣sem_otime才能變為非零值。另外,因為第一個進程可能不調用semop,或者semop操作需要很長時間,第二個進程可能無限期等待下去,或者等待很長時間。

7. 信號燈應用實例

本實例有兩個目的:1、獲取各種信號燈信息;2、利用信號燈實現共享資源的申請和釋放。並在程序中給出了詳細注釋。

include <sys/sem.h>include <unistd.h>define SEM_PATH &34;ifndef IPC_INFOendif int gi_semid;const int gi_semcnt = 1; union semun { int val; /* value for SETVAL */ struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */ unsigned short *array; /* array for GETALL & SETALL */ struct seminfo *__buf; /* buffer for IPC_INFO */ //test!! void *__pad; }; int main(){ int i_flag_create, i_flag_get, i_key, i, i_init_ok, i_tmperrno; struct semid_ds semid_ds_var; struct seminfo seminfo_var; union semun semun_arg; struct sembuf sembuf_ask, sembuf_free; i_flag_create = IPC_CREAT | IPC_EXCL | 00666; i_flag_get = IPC_CREAT | 00666; i_key = ftok( SEM_PATH, &39; ); //error handling for ftok here; i_init_ok = 0; gi_semid = semget( i_key, gi_semcnt, i_flag_create ); //create a semaphore set that only includes one semaphore. if( gi_semid < 0 ) { i_tmperrno = errno; perror( &34; ); if( i_tmperrno == EEXIST ) //errno is undefined after a successful library call( including perror call) //so it is saved in i_tmperrno. { gi_semid = semget( i_key, gi_semcnt, i_flag_get ); // i_flag_get 只包含了IPC_CREAT標誌, 參數nsems(這裡為1) // 必須與原來的信號燈數目一致 semun_arg.buf = &semid_ds_var; for ( i = 0; i < max_tries; i++ ) { printf( &34;, i ); if ( semctl( gi_semid, 0, IPC_STAT, semun_arg ) == -1 ) { perror( &34; ); i = max_tries; } else { if( semun_arg.buf->sem_otime != 0 ) // the create process already initialized the semaphore { i = max_tries; i_init_ok = 1; } else sleep(1); } } // for(i=0; i<max_tries; i++) if( !i_init_ok ) // do some initializing, here we assume that the first process that creates the sem // will finish initialize the sem and run semop in max_tries*1 seconds. else it will // not run semop any more. { printf( &34; ); semun_arg.val = 1; if ( semctl( gi_semid, 0, SETVAL, semun_arg ) == -1 ) perror( &34; ); } // if(!i_init_ok) } // if(i_tmperrno==EEXIST) else { perror(&34;); exit( 1 ); } } else //gi_semid>=0; do some initializing { printf( &34; ); semun_arg.val = 1; if ( semctl( gi_semid, 0, SETVAL, semun_arg ) == -1 ) perror( &34; ); } //get some information about the semaphore and the limit of semaphore in redhat8.0 semun_arg.buf=&semid_ds_var; if( semctl( gi_semid, 0, IPC_STAT, semun_arg ) == -1 ) perror(&34;); printf( &39;s uid is %d\n&34;owner&34;, semun_arg.buf->sem_perm.gid ); printf( &39;s uid is %d\n&34;creater&34;, semun_arg.buf->sem_perm.cgid ); semun_arg.__buf = &seminfo_var; if( semctl( gi_semid, 0, IPC_INFO, semun_arg ) == -1 ) perror( &34; ); printf( &34;, semun_arg.__buf->semmap ); printf( &34;, semun_arg.__buf->semmni ); printf( &34;, semun_arg.__buf->semmns ); printf( &34;, semun_arg.__buf->semmnu ); printf( &34;, semun_arg.__buf->semmsl ); printf( &34;, semun_arg.__buf->semopm ); printf( &34;, semun_arg.__buf->semume ); printf( &34;, semun_arg.__buf->semusz ); printf( &34;, semun_arg.__buf->semvmx ); // print sem_otime semun_arg.buf = &semid_ds_var; if ( semctl( gi_semid, 0, IPC_STAT, semun_arg ) == -1 ) { perror( &34; ); i = max_tries; } else { printf( &34;, semun_arg.buf->sem_otime ); } //now ask for available resource: printf( &34; ); sembuf_ask.sem_num = 0; sembuf_ask.sem_op = -1; sembuf_ask.sem_flg = SEM_UNDO; if( semop( gi_semid, &sembuf_ask, 1 ) == -1 ) //ask for resource perror(&34;); printf( &34; ); // print sem_otime semun_arg.buf = &semid_ds_var; if ( semctl( gi_semid, 0, IPC_STAT, semun_arg ) == -1 ) { perror( &34; ); i = max_tries; } else { printf( &34;, semun_arg.buf->sem_otime ); } sleep(5); //do some handling on the sharing resource here, just sleep on it 3 seconds printf( &34; ); //now free resource sembuf_free.sem_num = 0; sembuf_free.sem_op = 1; sembuf_free.sem_flg = SEM_UNDO; if ( semop( gi_semid, &sembuf_free, 1 ) == -1 ) //free the resource. if( errno == EIDRM ) printf( &34; ); //you can comment out the codes below to compile a different version: if( semctl( gi_semid, 0, IPC_RMID ) == -1 ) perror( &34; ); else printf(&34;); return 0;}

註:讀者可以嘗試一下注釋掉初始化步驟,進程在運行時會出現何種情況(進程在申請資源時會睡眠),同時可以像程序結尾給出的注釋那樣,把該程序編譯成兩個不同版本。下面是本程序的運行結果(作業系統gentoo):

create semaphore success, initialize itowner&39;s gid is 1007creater&39;s gid is 1007the number of entries in semaphore map is 32000 max number of semaphore identifiers is 128 mas number of semaphores in system is 32000 the number of undo structures system wide is 32000 max number of semaphores per gi_semid is 250 max number of ops per semop call is 32 max number of undo entries per process is 32 the sizeof of struct sem_undo is 20 the maximum semaphore value is 32767 before semop, semun_arg.buf->sem_otime: 0now ask the resourceask the resource successafter semop, semun_arg.buf->sem_otime: 1398501342now free the resourceremove sem ok

Summary:信號燈與其它進程間通信方式有所不同,它主要用於進程間同步。通常所說的系統V信號燈實際上是一個信號燈的集合,可用於多種共享資源的進程間同步。每個信號燈都有一個值,可以用來表示當前該信號燈代表的共享資源可用(available)數量,如果一個進程要申請共享資源,那麼就從信號燈值中減去要申請的數目,如果當前沒有足夠的可用資源,進程可以睡眠等待,也可以立即返回。當進程要申請多種共享資源時,linux可以保證操作的原子性,即要麼申請到所有的共享資源,要麼放棄所有資源,這樣能夠保證多個進程不會造成互鎖。Linux對信號燈有各種各樣的限制,程序中給出了輸出結果。另外,如果讀者想對信號燈作進一步的理解,建議閱讀sem.h原始碼,該文件不長,但給出了信號燈相關的重要數據結構。

相關焦點

  • 進程間通信之信號量semaphore--linux內核剖析
    常用於線程間同步。 而SYSTEM V信號量則是一個或多個信號量的集合,它對應的是一個信號量結構體,這個結構體是為SYSTEM V IPC服務的,信號量只不過是它的一部分。常用於進程間同步。name是直接將結構體中count值設置成n,此時信號量可用於實現進程間的互斥量。
  • 你未必知道 Linux作業系統進程間通信
    (一)無名管道,它具有幾個特點:  1) 管道是半雙工的,只能支持數據的單向流動;兩進程間需要通信時需要建立起兩個管道;  2) 無名管道使用pipe()函數創建,只能用於父子進程或者兄弟進程之間;  3) 管道對於通信的兩端進程而言,實質上是一種獨立的文件,只存在於內存中;  4) 數據的讀寫操作:一個進程向管道中寫數據,所寫的數據添加在管道緩衝區的尾部
  • Linux系統編程—信號量
    大家知道,互斥鎖可以用於線程間同步,但是,每次只能有一個線程搶到互斥鎖,這樣限制了程序的並發行。如果我們希望允許多個線程同時訪問同一個資源,那麼使用互斥鎖是沒有辦法實現的,只能互斥鎖會將整個共享資源鎖住,只允許一個線程訪問。這種現象,使得線程依次輪流運行,也就是線程從並行執行變成了串行執行,這樣與直接使用單進程無異。於是,Linux系統提出了信號量的概念。
  • 6種Linux進程間的通信方式
    但很多情況下進程間需要互相通信,來完成系統的某項功能。進程通過與內核及其它進程之間的互相通信來協調它們的行為。進程通信的應用場景數據傳輸:一個進程需要將它的數據發送給另一個進程,發送的數據量在一個字節到幾兆字節之間。共享數據:多個進程想要操作共享數據,一個進程對共享數據的修改,別的進程應該立刻看到。
  • linux多線程同步—信號量
    linux多線程編程-信號量信號量機制信號量機制在作業系統裡面學習的比較熟悉了,信號量是一個整數計數器,其數值表示空閒臨界資源的數量。當有進程釋放資源時,信號量增加,表示可用資源數增加;當有進程申請到資源時,信號量減少,表示可用資源數減少。這個時候可以把鎖機制認為是0-1信號量。
  • 官方唯一推薦的Linux內核剖析文檔《深入理解Linux內核》免費分享
    從20世紀90年代末開始,Linux 這位相對較新的成員突然變得非常流行,並且躋身於那些知名的商用Unix作業系統之列如果你是某種語言的開發者,你從事這個行業,不管你怎麼學習下去,linux永遠繞不開。
  • linux環境高級編程-高級IO和進程間通信詳解
    進程間通信介紹了基本進程間通信機制,包括兩大類:進程間數據共享:管道,FIFO,消息隊列和共享存儲進程間數據同步:信號量網絡進程間通信介紹網絡間的進程通信機制:套接字。高級進程間通信高級進程間通信提供一種可以在進程間傳遞文件描述符的機制,包括STREAMS管道和unix域套接字需要C/C++ Linux伺服器架構師學習資料後臺私信「資料」(資料包括C/C++,Linux,
  • Linux系統編程—進程間同步
    我們知道,線程間同步有多種方式,比如:信號量、互斥量、讀寫鎖,等等。那進程間如何實現同步呢?本文介紹兩種方式:互斥量和文件鎖。互斥量mutex我們已經知道了互斥量可以用於在線程間同步,但實際上,互斥量也可以用於進程間的同步。為了達到這一目的,可以在pthread_mutex_init初始化之前,修改其屬性為進程間共享。
  • Linux內核-進程間通信組件的實現
    ,進程間通信,虛擬文件系統和網絡接口。由於不用的用戶進程擁有不同的進程空間,因此進程間的通信要藉助於內核的中轉來實現。一般情況下,當一個進程等待硬體操作完成時,會被掛起。當硬體操作完成,進程被恢復執行,而協調這個過程的就是進程間的通信機制。三、進程間通信進程間通信主要用於控制不同進程之間在用戶空間的同步、數據共享和交換。
  • Linux後臺伺服器開發——Linux下進程間通信的方式有哪些?
    Linux下進程間通信的方式有:管道消息隊列信號信號量共享存儲套接字一、管道管道是半雙工的,數據只能向一個方向流動;需要雙方通信時,需要建立起兩個管道>FIFO命名管道詳情參閱:https://blog.csdn.net/qq_41453285/article/details/89472561匿名管道,由於沒有名字,只能用於親緣關係的進程間通信。
  • linux內核講解
    進程間6種通信方式,管道,消息隊列,信號量,共享內存5. 多個進程之間通信,如何實現通信組件6. 內核模塊操作,insmod, rmmod, lsmod, dmesg7.網卡測試實現四,自主思考項目:,Linux內核之虛擬網卡,C1000k案例如果感興趣的話可以去我的linux源碼內核頻道去看King老師的視頻講解,或者來我們公開課堂上跟講師們面對面交流。
  • linux下通過共享內存和mmap實現進程間通訊
    前言最近在學習GNU/linux內核,看到mmap的時候書上說:mmap/munmap接口函數是用戶最常用的兩個系統調用接口,無論是在用戶程序中分配內存、讀寫大文件、連結動態庫文件,還是多進程間共享內存,都可以看到mmap/munmap的身影。
  • linux用戶空間與內核空間通信——Netlink通信機制
    一:什麼是Netlink通信機制Netlink是linux提供的用於內核和用戶態進程之間的通信方式但是注意雖然Netlink主要用於用戶空間和內核空間的通信,但是也能用於用戶空間的兩個進程通信。只是進程間通信有其他很多方式,一般不用Netlink。
  • Linux信號量(3)-內核信號量
    我們有時候會等待電梯、洗手間,這種場景需要等待的時間並不是很多,如果我們還要找個地方睡一覺,然後等電梯到了或者洗手間可以用了再醒來,那很顯然這也沒有必要,我們只需要排好隊,刷一刷抖音就可以了,對比於電腦程式,比如驅動在進入中斷例程,在等待某個寄存器被置位,這種場景需要等待的時間往往很短暫,系統開銷甚至遠小於進入休眠的開銷,所以這種場景採用自旋鎖比較合適。
  • 常見的Linux系統調用
    按照筆者的理解,對其作了大致的分類,同時也作了一些小小的修改,刪去了幾個僅供內核使用,不允許用戶調用的系統調用,對個別本人稍覺不妥的地方作了一些小的修改,並對所有列出的系統調用附上簡要注釋。其中有一些函數的作用完全相同,只是參數不同。(可能很多熟悉C 朋友馬上就能聯想起函數重載,但是別忘了Linux核心是用C語言寫的,所以只能取成不同的函數名)。
  • Linux信號量(2)-POSIX 信號量
    無名信號量只可以在共享內存的情況下,比如實現進程中各個線程之間的互斥和同步,因此無名信號量也被稱作基於內存的信號量;命名信號量通常用於不共享內存的情況下,比如進程間通信。無名信號量只能存在於內存中,要求使用信號量的進程必須能訪問信號量所在的這一塊內存,所以無名信號量只能應用在同一進程內的線程之間(共享進程的內存),或者不同進程中已經映射相同內存內容到它們的地址空間中的線程(即信號量所在內存被通信的進程共享)。意思是說無名信號量只能通過共享內存訪問。相反,有名信號量可以通過名字訪問,因此可以被任何知道它們名字的進程中的線程使用。
  • 免費《linux內核開發100講》更新時間、講解方式、內容大綱的約定
    三、關於內容:考慮到內核代碼的複雜性,剛開始的時候我會儘量從邏輯上來帶大家理解,之後會循序漸進的通過代碼來驗證。這是人類在認識陌生事物的一個普遍思路。我相信這種方法是科學的。有人問我要大綱,我其實是有大綱的,但是還不夠細化。因為大綱把人思路禁錮死了。
  • linux進程調度淺析
    而linux在缺頁異常的處理代碼中試圖分配內存時,又可能由於系統內存緊缺而分配失敗,導致進程進入睡眠; 2、代碼執行過程中硬體產生中斷,linux進入中斷處理程序而擱置當前進程。而中斷處理程序的處理過程中又可能發生新的硬體中斷,中斷永遠嵌套不止……;等等…… 而像linux這樣號稱實現了「實時」的通用作業系統,其實只是實現了「軟實時」,即儘可能地滿足進程的實時需求。
  • 進程間的五種通信方式介紹
    進程間通信又叫IPC (InterProcess Communication)是指在不同進程之間傳播或交換信息。IPC的方式通常有管道(包括無名管道和命名管道)、消息隊列、信號量、共享存儲、Socket。 Socket支持不同主機上的兩個進程IPC。
  • linux基礎命令(進程管理)
    用三種命令分別查看redis-server進程的pidlinux-szge:/home/soft # pgrep redis-server 1560linux-szge:/home/soft # pidof redis-server1560linux-szge:/home/soft # ps aux | grep