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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

Linux系统编程常见函数 (进程/线程)

發布時間:2024/4/24 综合教程 35 生活家
生活随笔 收集整理的這篇文章主要介紹了 Linux系统编程常见函数 (进程/线程) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Lunix系統編程函數多且復雜,本文記錄一下Linux系統編程最最常用的哪些函數以及這些函數的常見用法。當然本文不可能囊括所有,所以在編程時候最好的學習方法還是查看manpage,多看多寫,熟能生巧。

而且這里只是總結一下函數的最常用的用法和參數,相關知識還是要看書看視頻學習的。

博主學習Linux編程不久,水平有限文章有錯誤還請各位不吝指出。廢話不多說,開始咯。

這篇主要歸納進程和線程相關的函數,文件和目錄操作看上一篇:https://www.cnblogs.com/clno1/p/12935626.html。

進程相關:

fork函數:

pid_t fork(void);  作用是創建一個子進程。

失敗返回-1;成功返回:① 父進程返回子進程的 ID(非負) ②子進程返回 0 (亦即我們用fork返回值判斷當前是父/子進程)

父子相同處: 全局變量、.data、.text、棧、堆、環境變量、用戶 ID、宿主目錄、進程工作目錄、信號處理方式...

父子不同處: 1.進程 ID 2.fork 返回值 3.父進程 ID 4.進程運行時間 5.鬧鐘(定時器) 6.未決信號集

父子進程的copyonwrite機制:https://www.pianshen.com/article/4305691855/

getpid函數:

pid_t getpid(void);  作用是獲取當前進程 ID(返回值)

getppid函數:

pid_t getppid(void);  獲取當前進程的父進程 ID(返回值)

getuid 函數:

獲取當前進程實際用戶 ID  uid_t getuid(void);

獲取當前進程有效用戶 ID  uid_t geteuid(void);

getgid 函數

獲取當前進程使用用戶組 ID  gid_t getgid(void);

獲取當前進程有效用戶組 ID  gid_t getegid(void);

孤兒進程與講師進程,以及回收子進程:

https://www.cnblogs.com/clno1/p/12937547.html

守護進程相關:

https://www.cnblogs.com/clno1/p/12941308.html

進程間通信:

在操作系統歷史中出現了很多IPC,如文件、管道、信號、共享內存、消息隊列、套接字、命名管道等。但是現今常用的進程間通信方式有:① 管道 (使用最簡單) ,② 信號 (開銷最小),③ 共享映射區 (無血緣關系),④ 本地套接字 (最穩定

匿名管道PIPE:

int pipe(int pipefd[2]);   函數作用創建匿名管道。成功:0;失敗:-1,設置 errno;

函數調用成功返回 r/w 兩個文件描述符。無需 open,但需手動 close。規定:fd[0] → r; fd[1] → w,就像 0對應標準輸入,1 對應標準輸出一樣。向管道文件讀寫數據其實是在讀寫內核緩沖區。

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #include<string.h>
 4 #include<unistd.h>
 5 #include<errno.h>
 6 #include<pthread.h>
 7 
 8 void sys_err(const char *str) {
 9     perror(str);
10     exit(1);
11 }
12 
13 int main(int argc,char *argv[])
14 {
15     int fd[2];
16     int ret;
17     pid_t pid;
18 
19     ret=pipe(fd);        //創建管道
20     if (ret==-1) sys_err("pipe error");
21 
22 
23     pid=fork();        //創建子進程
24     
25     //父子進程合作完成ls wc -l
26     if (pid==-1)         //失敗
27         sys_err("fork error");    
28     else if (pid>0) {    //父進程完成wc -l
29         close(fd[1]);    //父進程讀,關閉寫端
30         dup2(fd[0],STDIN_FILENO);    //有讀端且為空,pipe會阻塞到讀到數據
31         execlp("wc","wc","-l",NULL);
32         sys_err("exclp wc error");    //一旦執行了execlp就結束了,沒法走到這里,所以這里可以用來判錯
33     } else if (pid==0) {    //子進程完成ls
34         close(fd[0]);    //子進程寫,關閉讀端
35         dup2(fd[1],STDOUT_FILENO);
36         execlp("ls","ls",NULL);
37         sys_err("exclp ls error");
38     }    
39     return 0;
40 }

PIPE完成ls wc -l

命名管道FIFO:

匿名管道(pipe)只能用于“有血緣關系”的進程間。但通過 FIFO,不相關的進程也能交換數據。FIFO 是 Linux 基礎文件類型中的一種。但,FIFO 文件在磁盤上沒有數據塊,僅僅用來標識內核中一條通道。各

進程可以打開這個文件進行 read/write,實際上是在讀寫內核通道,這樣就實現了進程間通信。

創建方式:1. 命令:mkfifo 管道名  2. 庫函數:int mkfifo(const char *pathname, mode_t mode); 成功:0; 失敗:-1

一旦使用 mkfifo 創建了一個 FIFO,就可以使用 open 打開它,常見的文件 I/O 函數都可用于 fifo。如:close、read、write、unlink 等

共享映射區MMap:

原理是將一個磁盤文件映射到內存地址空間緩沖區,于是當從緩沖區中取數據,就相當于讀文件中的相應字節。于此類似,將數據存入緩沖區,則相應的字節就自動寫入文件。

mmap 函數
void *mmap(void *adrr, size_t length, int prot, int flags, int fd, off_t offset);  函數作用是建立映射文件。
返回:成功:返回創建的映射區首地址; 失敗:MAP_FAILED 宏
addr: 建立映射區的首地址,由 Linux 內核指定。使用時,直接傳遞 NULL
length: 欲創建映射區的大小
prot: 映射區權限 PROT_READ、PROT_WRITE、PROT_READ|PROT_WRITE
flags: 標志位參數(常用于設定更新物理區域、設置共享、創建匿名映射區)
    MAP_SHARED: 會將映射區所做的操作反映到物理設備(磁盤)上。
    MAP_PRIVATE: 映射區所做的修改不會反映到物理設備。
fd: 用來建立映射區的文件描述符
offset: 映射文件的偏移(4k 的整數倍)

父子等有血緣關系的進程之間也可以通過 mmap 建立的映射區來完成數據通信。但相應的要在創建映射區的時候指定對應的標志位參數 flags:

MAP_PRIVATE: (私有映射) 父子進程各自獨占映射區;  MAP_SHARED: (共享映射) 父子進程共享映射區;

munmap 函數

int munmap(void *addr, size_t length);  函數作用是釋放剛剛建立映射的內存緩沖區。

返回值: 成功:0; 失敗:-1 errno

信號:

信號重要且相對復雜,開新篇總結:https://www.cnblogs.com/clno1/p/12941316.html

線程相關:

線程(ight weight process)稱為輕量級的進程,本質仍是進程(在 Linux 環境下),一個區別在于:進程,獨立地址空間,擁有 PCB 。線程,有獨立的 PCB,但沒有獨立的地址空間(共享)。

線程共享資源  1.文件描述符表2.每種信號的處理方式3.當前工作目錄4.用戶 ID 和組 ID5.內存地址空間 (.text/.data/.bss/heap/共享庫)

線程非共享資源  1.線程 id2.處理器現場和棧指針(內核棧)3.獨立的棧空間(用戶空間棧)4.errno 變量5.信號屏蔽字6.調度優先級

pthread_create 函數

int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);  創建一個新線程。 其作用,對應進程中 fork() 函數。

返回值:成功:0; 失敗:錯誤號 -----Linux 環境下,所有線程特點,失敗均直接返回錯誤號。

參數:pthread_t:當前 Linux 中可理解為:typedef unsigned long int pthread_t;

參數 1:傳出參數,保存系統為我們分配好的線程 ID
參數 2:通常傳 NULL,表示使用線程默認屬性。若想使用具體屬性也可以修改該參數
參數 3:函數指針,指向線程主函數(線程體),該函數運行結束,則線程結束。
參數 4:線程主函數執行期間所使用的參數。  (即參數3和4描述了線程的函數)

pthread_self 函數

pthread_t pthread_self(void);  獲取線程 ID。其作用對應進程中 getpid() 函數。  返回值:成功:0; 失敗:無!

線程 ID:pthread_t 類型,本質:在 Linux 下為無符號整數(%lu),其他系統中可能是結構體實現

線程 ID 是進程內部,識別標志。(兩個進程間,線程 ID 允許相同)

注意:不應使用全局變量 pthread_t tid,在子線程中通過 pthread_create 傳出參數來獲取線程 ID,而應使用pthread_self。

pthread_exit 函數

void pthread_exit(void *retval);  將單個線程退出  參數:retval 表示線程退出狀態,通常傳 NULL

pthread_join 函數

int pthread_join(pthread_t thread, void **retval);  阻塞等待線程退出,獲取線程退出狀態 其作用,對應進程中 waitpid() 函數。  成功:0;失敗:錯誤號

參數:thread:線程 ID (【注意】:不是指針);retval:存儲線程結束狀態。

pthread_detach 函數

int pthread_detach(pthread_t thread);  實現線程分離  成功:0;失敗:錯誤號

線程分離狀態:指定該狀態,線程主動與主控線程斷開關系。線程結束后,其退出狀態不由其他線程獲取,而直接自己自動釋放。網絡、多線程服務器常用。

一般情況下,線程終止后,其終止狀態一直保留到其它線程調用 pthread_join 獲取它的狀態為止。但是線程也可以被置為 detach 狀態, 這樣的線程一旦終止就立刻回收它占用的所有資源,而不保留終止狀態。

不能對一個已經處于 detach 狀態的線程調用 pthread_join,這樣的調用將返回 EINVAL 錯誤。也就是說,如果已經對一個線程調用了 pthread_detach 就不能再調用 pthread_join 了。

也可使用 pthread_create 函數參 2(線程屬性)來設置線程分離。

pthread_cancel 函數

int pthread_cancel(pthread_t thread);  殺死(取消)線程 其作用,對應進程中 kill() 函數。  成功:0;失敗:錯誤號

值得注意的是:線程的取消并不是實時的,而有一定的延時。需要等待線程到達某個取消點(檢查點)。

取消點:是線程檢查是否被取消,并按請求進行動作的一個位置。通常是一些系統調用 creat,open,pause,close,read,write..... 執行命令 man 7 pthreads 可以查看具備這些取消點的系統調用列表。

可粗略認為一個系統調用(進入內核)即為一個取消點。如線程中沒有取消點,可以通過調用 pthread_testcancel函數自行設置一個取消點。

總結:終止某個線程而不終止整個進程,有三種方法:
1. 從線程主函數 return。這種方法對主控線程不適用,從 main 函數 return 相當于調用 exit。
2. 一個線程可以調用 pthread_cancel 終止同一進程中的另一個線程。
3. 線程可以調用 pthread_exit 終止自己。

線程同步:https://www.cnblogs.com/clno1/p/12942972.html

總結

以上是生活随笔為你收集整理的Linux系统编程常见函数 (进程/线程)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。