Linux高并發服務器開發 第十九天(線程 進程)

目錄

1.進程組和會話

2.守護進程

2.1守護進程daemon概念?

2.2創建守護進程

3.線程

3.1線程的概念

3.2線程內核三級映射

3.3線程共享

3.4線程優缺點

4.線程控制原語

4.1獲取線程id

4.2創建線程

4.3循環創建N個子線

4.4子線程傳參地址,錯誤示例

4.5線程退出

4.6線程回收

4.6.1回收示例1

4.6.2回收示例2

4.7線程分離

4.8殺死(取消)線程

4.8.1終止線程方法


1.進程組和會話

- 進程聚集成為進程組,多個進程組聚集成為會話。

- ps ajx //查看 進程組id ?和 會話id

- 創建會話 setsid()

?pid_t setsid(void);?

- 組長進程不能作為新會話的首進程,因此 fork() 后,終止父進程,子進程調用 setsid() 創建會話,以自己的進程pid, 為會話id 和 進程組 id。

2.守護進程

2.1守護進程daemon概念?

- Linux后臺的一些服務進程,沒有控制終端,不能直接和用戶交互。不受用戶登錄、注銷的影響,一直在后臺運行。周期性的執行某種任務,或者等待某一事件的發生。 一般采用以d 結尾的命名方式。

2.2創建守護進程

int main(int argc, char *argv[])
{pid_t pid;int ret, fd;pid = fork();?? ??? ?// 創建子進程if (pid > 0)exit(0);?? ??? ?// 終止父進程pid = setsid();?? ??? ?// 子進程創建新會話.if (pid == -1)sys_err("setsid err");ret = chdir("/home/itcast/bj_40"); ?// 改變工作目錄if (ret == -1)sys_err("chdir err");umask(0);?? ??? ??? ?// 改變文件訪問權限掩碼,沒有屏蔽任何權限close(STDIN_FILENO);// 關閉標準輸入文件描述符fd = open("/dev/null", O_RDWR); ? // fd ---> 0if (fd == -1)sys_err("open err");dup2(fd, STDOUT_FILENO);dup2(fd, STDERR_FILENO);while (1);?? ??? ??? ?// 模擬守護進程業務return 0;
}

3.線程

3.1線程的概念

- Linux 系統中,線程 LWP 稱之為:輕量級的進程。
- 進程:有獨立的進程地址空間, 有獨立的 pcb。 —— 最小資源分配單位。
- 線程:有獨立的pcb,沒有獨立的進程地址空間。(與其他線程共享) —— 最小執行單位。

- 一個創建了線程的進程,本身也淪落 為線程。

- LWP 號: cpu 劃分時間片依據。 ?—— 線程 最小執行單位。
- 查看LWP號命令: ps -Lf 進程pid?

3.2線程內核三級映射

- 三級映射。—— 解釋了,為什么線程沒有獨立的進程地址空間。

3.3線程共享

- 獨享:棧空間(用戶棧、內核棧)errnum?
- 共享:./text ?./ordata ?./data ?./bss ?heap堆 ----> 共享全局變量

3.4線程優缺點

- 優點:
? ? - 并發性強。 ?
? ? - 開銷小。
? ? - 數據通信方便。
- 缺點:
? ? - 庫函數,穩定性差。
? ? - 調試、編寫困難
? ? - 對信號支持差。
- 結論:既能使用進程開發,也能使用線程開發的程序,首選 線程。

4.線程控制原語

4.1獲取線程id

#include <pthread.h>

pthread_t pthread_self(void); ??// 獲取線程id, 在進程內部標識線程身份。

返回值:線程id

4.2創建線程

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
?????????????????? void *(*start_routine) (void *), void *arg);

參1: 傳出參數,新子線的 線程id
參2: 線程屬性。默認傳 NULL, 表使用默認屬性。
參3: 子線程回調函數。pthread_create 調用成功,該函數會被自動調用起來。
參4: 參3 的參數。

返回值:
????成功:0
????失敗:直接返回錯誤號!

- 線程中處理出錯, 只能使用 strerror() , 不能使用 perror() ,舉例如下:

#include <string.h>char *strerror(int errnum);
fprintf(stderr, "xxx error:%s\n", strerror(錯誤號));

- 創建子線程

// 子線程主函數
void *tfn(void *arg)
{printf("tfn : pid = %d, pthread_id = %lu\n", getpid(), pthread_self());return NULL;
}int main(int argc, char *argv[])
{pthread_t tid;// 創建子線程int ret = pthread_create(&tid, NULL, tfn, NULL);if (ret != 0)fprintf(stderr, "pthread_create err:%s\n", strerror(ret));printf("main : pid = %d, pthread_id = %lu\n", getpid(), pthread_self());sleep(1);????????// 給子線程執行時間return 0;????????// 釋放進程地址空間
}

4.3循環創建N個子線

- 每個子線程打印,自己是第幾個被創建出來。

void *tfn(void *arg)
{int i = (int)(long)arg;printf("I'm %dth thread: pid= %d, tid= %lu\n", i+1, getpid(), pthread_self());return NULL;
}int main(int argc, char *argv[])
{int i, ret;pthread_t tid;for (i = 0; i < 5; i++) {ret = pthread_create(&tid, NULL, tfn, (void *)(long)i);if (ret != 0)fprintf(stderr, "pthread_create err:%s\n", strerror(ret));}//sleep(i);usleep(10000);printf("I'm main thread: pid= %d, tid= %lu\n", getpid(), pthread_self());return 0;
}

4.4子線程傳參地址,錯誤示例

4.5線程退出

void pthread_exit(void *retval);

參:代表線程的退出值。 無退出值,NULL

- 結論:
? ? - return:返回到調用者那里。
? ? - exit(): 退出當前進程。
? ? - pthread_exit(): 退出當前線程。

4.6線程回收

// 阻塞 回收線程。
int pthread_join(pthread_t thread, void **retval);


參1:待回收的線程id
參2:傳出參數。回收的那個線程的 退出值。
?? ?進程中:main返回值:return 0、 exit(1) ?---> int。 回收進程退出值 wait(int *)
? ? 線程中:線程返回值:pthread_exit --> void *。 回收線程退出值 pthread_join(void **)


返回值:
?? ?成功:0
?? ?失敗:直接返回錯誤號!

4.6.1回收示例1
// 子線程主題函數
void *tfn(void *arg)
{sleep(5);//return (void *)74;pthread_exit((void *)"hello");
}int main(int argc, char *argv[])
{pthread_t tid;//int *retval; ? ?// 用來存儲子進程退出值char *retval; ? ?// 用來存儲子進程退出值// 創建子線程int ret = pthread_create(&tid, NULL, tfn, NULL);if (ret != 0)fprintf(stderr, "pthread_create err:%s\n", strerror(ret));printf("----------------1\n");// 回收子線程退出值ret = pthread_join(tid, (void **)&retval);if (ret != 0)fprintf(stderr, "pthread_join err:%s\n", strerror(ret));printf("child thread exit with %s\n", (char *)retval);pthread_exit((void *)0);?? ??? ?// 退出主線程
}
4.6.2回收示例2
struct thrd {int var;char str[256];
};// 子線程主題函數
void *tfn(void *arg)
{struct thrd *tval = (struct thrd *)arg;?? ??? ??? ?//malloc()tval->var = 100;strcpy(tval->str, "hello thread");pthread_exit((void *)tval);// return (void *)tval;?? ??? ??? ??? ?// 也可以
}int main(int argc, char *argv[])
{pthread_t tid;struct thrd arg, *retval;// 創建子線程int ret = pthread_create(&tid, NULL, tfn, (void *)&arg);if (ret != 0)fprintf(stderr, "pthread_create err:%s\n", strerror(ret));// 回收子線程退出值ret = pthread_join(tid, (void **)&retval);if (ret != 0)fprintf(stderr, "pthread_join err:%s\n", strerror(ret));printf("child exit with: var = %d, str= %s\n", retval->var, retval->str);// free();pthread_exit((void *)0);?? ??? ?// 退出主線程
}

4.7線程分離

- 與進程類似,線程結束時,也有 “僵尸線程” 產生。消耗系統資源。

int pthread_detach(pthread_t thread); ?// 設置線程為分離態


參:待設置為分離的線程id

- 設置為分離態的線程,在終止時,會自動清理 pcb 內核殘留。
- 對于已經分離的線程,使用 pthread_join() 不能正常回收。不能獲取線程退出值。

4.8殺死(取消)線程

int pthread_cancel(pthread_t thread);


參:待殺死的線程id

1. 被 pthread_cancel() 殺死的線程,在使用 pthread_join() 回收,得到的退出值 -1。?
2. pthread_cancel() 殺死線程必須要到達一個 “取消點” (保存點), 才能生效。否則無法殺死線程。
? ? - 應該在被cancel的線程中,調用 pthread_testcancel() 函數來添加 “取消點” (保存點)

4.8.1終止線程方法

1. return
2. pthread_exit()
3. pthread_cancel() ? 需要 “保存點”。 —— 進內核,即可得到。

線程進程控制原語比對:

| 線程控制原語? ? ? ? ?| 進程控制原語|
| -------------------------?| -----------------?|
| pthread_create()? ? ?| fork()? ? ? ? ? ?? |
| pthread_self()? ? ? ? ?| getpid()? ? ? ? ? |
| pthread_exit()? ? ? ? ?| exit()? ? ? ? ? ? ? |
| pthread_join()? ? ? ? ?| wait/waitpid()?|
| pthread_cancel()? ??| kill()? ? ? ? ? ? ? ? |
| pthread_detach()? ? |? ? ? ? ? ? ? ? ? ? ? ?|
?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/71766.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/71766.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/71766.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

軟件工程和系統分析與設計

軟件工程 1、軟件危機 2、軟件過程模型 2.1 瀑布模型 2.2原型模型 2.3螺旋模型 2.4敏捷模型 2.5軟件統一過程 3、軟件能力成熟度模型 CMM 4、軟件能力成熟度模型集成 CMMI 系統分析與設計 1、結構化方法SASD 1.1結構化分析 DFD 1.2結構化設計 SD-是一種面向數據流的設計…

Qt/C++面試【速通筆記一】

Qt 信號與槽機制 什么是信號&#xff08;Signal&#xff09;和槽&#xff08;Slot&#xff09;&#xff1f; 在Qt中&#xff0c;信號&#xff08;Signal&#xff09;和槽&#xff08;Slot&#xff09;是實現對象之間通信的一種機制。信號是對象在某些事件發生時發出的通知&…

LangChain大模型應用開發:構建Agent智能體

介紹 大家好&#xff0c;博主又來給大家分享知識了。今天要給大家分享的內容是使用LangChain進行大模型應用開發中的構建Agent智能體。 在LangChain中&#xff0c;Agent智能體是一種能夠根據輸入的任務或問題&#xff0c;動態地決定使用哪些工具(如搜索引擎、數據庫查詢等)來…

微服務架構概述及創建父子項目

目錄 一&#xff0c;什么是單體架構 二&#xff0c;什么是集群和分布式架構 三&#xff0c;什么是微服務架構 四&#xff0c;解決微服務難題的方案Spring-cloud Spring Cloud Alibaba是阿里巴實現的方案&#xff0c;基于SpringCloud的規范。如果說Spring Cloud Netflix 是…

C/C++跳動的愛心

系列文章 序號直達鏈接1C/C李峋同款跳動的愛心2C/C跳動的愛心3C/C經典愛心4C/C滿屏飄字5C/C大雪紛飛6C/C炫酷煙花7C/C黑客帝國同款字母雨8C/C櫻花樹9C/C奧特曼10C/C精美圣誕樹11C/C俄羅斯方塊小游戲12C/C貪吃蛇小游戲13C/C孤單又燦爛的神14C/C閃爍的愛心15C/C哆啦A夢16C/C簡單…

量子計算的威脅,以及企業可以采取的措施

當谷歌、IBM、Honeywell和微軟等科技巨頭紛紛投身量子計算領域時&#xff0c;一場技術軍備競賽已然拉開帷幕。 量子計算雖能為全球數字經濟帶來巨大價值&#xff0c;但也有可能對相互關聯的系統、設備和數據造成損害。這一潛在影響在全球網絡安全領域引起了強烈關注。也正因如…

Unity制作游戲——前期準備:Unity2023和VS2022下載和安裝配置——附安裝包

1.Unity2023的下載和安裝配置 &#xff08;1&#xff09;Unity官網下載地址&#xff08;國際如果進不去&#xff0c;進國內的官網&#xff0c;下面以國內官網流程為例子&#xff09; unity中國官網&#xff1a;Unity中國官網 - 實時內容開發平臺 | 3D、2D、VR & AR可視化 …

23貪心算法

分發餅干 class Solution { public:int findContentChildren(vector<int>& g, vector<int>& s) {int i0,j0;int count0;sort(s.begin(),s.end());sort(g.begin(),g.end());while(i<g.size()&&j<s.size()){if(g[i]<s[j]){i;j;count;}else…

Spark 和 Flink

Spark 和 Flink 都是目前流行的大數據處理引擎&#xff0c;但它們在架構設計、應用場景、性能和生態方面有較大區別。以下是詳細對比&#xff1a; 1. 架構與核心概念 方面Apache SparkApache Flink計算模型微批&#xff08;Micro-Batch&#xff09;為主&#xff0c;但支持結構…

Android 串口通信

引言 在iot項目中&#xff0c;Android 端總會有和硬件通信。 通信這里&#xff1a;串口通信&#xff0c;藍牙通信或者局域網通信。 這里講一下串口通信。 什么是串口&#xff1f; “串口”&#xff08;Serial Port&#xff09;通常是指一種用于與外部設備進行串行通信的接口。…

【計算機網絡】OSI模型、TCP/IP模型、路由器、集線器、交換機

一、計算機網絡分層結構 計算機網絡分層結構 指將計算機網絡的功能劃分為多個層次&#xff0c;每個層次都有其特定的功能和協議&#xff0c;并且層次之間通過接口進行通信。 分層設計的優勢&#xff1a; 模塊化&#xff1a;各層獨立發展&#xff08;如IPv4→IPv6&#xff0c…

從人機環境系統智能角度看傳統IP的全球化二次創作法則

從人機環境系統智能的視角看&#xff0c;傳統IP的全球化二次創作法則需結合技術、文化、倫理與環境的復雜協同。這一過程不僅是內容的本土化改編&#xff0c;更是人、機器與環境在動態交互中實現價值共創的體現。 一、人機環境系統智能的底層邏輯與IP二次創作的融合 1、感知層&…

實現 INFINI Console 與 GitHub 的單點登錄集成:一站式身份驗證解決方案

本文將為您詳細解析如何通過 GitHub OAuth 2.0 協議&#xff0c;為 INFINI Console 實現高效、安全的單點登錄&#xff08;Single Sign-On, SSO&#xff09;集成。通過此方案&#xff0c;用戶可直接使用 GitHub 賬戶無縫登錄 INFINI Console&#xff0c;簡化身份驗證流程&#…

記一次復雜分頁查詢的優化歷程:從臨時表到普通表的架構演進

1. 問題背景 在項目開發中&#xff0c;我們需要實現一個復雜的分頁查詢功能&#xff0c;涉及大量 IP 地址數據的處理和多表關聯。在我接手這個項目的時候,代碼是這樣的 要知道代碼里面的 ipsList 數據可能幾萬條甚至更多,這樣拼接的sql,必然是要內存溢出的,一味地擴大jvm參數不…

C++關鍵字之mutable

1.介紹 在C中&#xff0c;mutable是一個關鍵字&#xff0c;用于修飾類的成員變量。它的主要作用是允許在常量成員函數或常量對象中修改被標記為mutable的成員變量。通常情況下&#xff0c;常量成員函數不能修改類的成員變量&#xff0c;但有些情況下&#xff0c;某些成員變量的…

云計算中的API網關是什么?為什么它很重要?

在云計算架構中&#xff0c;API網關&#xff08;API Gateway&#xff09;是一個重要的組件&#xff0c;主要用于管理、保護和優化不同服務之間的接口&#xff08;API&#xff09;通信。簡單來說&#xff0c;API網關就像是一個中介&#xff0c;它充當客戶端和后端服務之間的“橋…

深搜專題2:組合問題

描述 組合問題就是從n個元素中抽出r個元素(不分順序且r < &#xff1d; n)&#xff0c; 我們可以簡單地將n個元素理解為自然數1&#xff0c;2&#xff0c;…&#xff0c;n&#xff0c;從中任取r個數。 例如n &#xff1d; 5 &#xff0c;r &#xff1d; 3 &#xff0c;所…

uniapp多端適配

UniApp是一個基于Vue.js開發多端應用的框架&#xff0c;它可以讓開發者編寫一次代碼&#xff0c;同時適配iOS、Android、Web等多個平臺。 環境搭建&#xff1a; UniApp基于Vue.js開發&#xff0c;所以需要先安裝Vue CLI npm install -g vue/cli 創建一個新的UniApp項目&…

Error [ERR_REQUIRE_ESM]: require() of ES Module

報錯信息&#xff1a; 【報錯】Message.js 導入方式不對&#xff0c;用的是 ES Moudle 的語法&#xff0c;提示使用 import 引入文件 項目開發沒有用到 js-message 依賴&#xff0c;是 node-ipc 依賴中用到的 js-message 依賴&#xff0c; node-ipc 中限制 js-message 版本&a…

給小米/紅米手機root(工具基本為官方工具)——KernelSU篇

目錄 前言準備工作下載刷機包xiaomirom下載刷機包【適用于MIUI和hyperOS】“hyper更新”微信小程序【只適用于hyperOS】 下載KernelSU刷機所需程序和驅動文件 開始刷機設置手機第一種刷機方式【KMI】推薦提取boot或init_boot分區 第二種刷機方式【GKI】不推薦 結語 前言 刷機需…