Linux系統編程 day9 SIGCHLD and 線程

SIGCHLD信號

只要子進程信號發生改變,就會產生SIGCHLD信號。

借助SIGCHLD信號回收子進程

回收子進程只跟父進程有關。如果不使用循環回收多個子進程,會產生多個僵尸進程,原因是因為這個信號不會循環等待。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<pthread.h>
#include<sys/wait.h>
#include<signal.h>void catch_child(int signo) //有子進程終止,發送sigchld信號時,該函數會被內核回調
{pid_t wpid;int status;//while((wpid = wait(NULL))!= -1);while((wpid = waitpid(-1 , &status , 0))!= 0 ){if(WISEXITED(status))printf("catch child:%d , status: %d\n" ,wpid , WEXITSTATUS(status));}
}int main(int argc , char *argv[])
{pid_t pid;int i ;//阻塞sigset_t set ;  // 防止在父進程創建sa_mask之前子進程先死亡。sigemptyset(&set);sigaddset(&set , SIGCHLD);sigprocmask(SIG_BLOCK , &set , NULL);for(i = 0 ; i < 5 ; i++){if((pid = fork()) == 0)break;}if(i == 5){struct sigaction act;act.sa_handler = catch_child;sigemptyset(&act.sa_mask);act.sa_flags = 0;sigaction(SIGCHLD , &act , NULL);//解除阻塞sigprocmask(SIG_UNBLOCK , &set , NULL);printf("I am parent , %d\n" , getpid());}else{printf("I am child , %d\n" , getpid());}return 0 ;
}

中斷系統調用(非重點)

系統調用分為兩類:慢速系統調用和其他系統調用。

慢速系統調用:可能會使進程永遠阻塞的一類。eg. read write wait and so on .

其他系統調用:getpid()....

sa_flags 用來設置被信號中斷后系統調用是否重啟。

進程組和會話

進程組也稱之為作業。

創建會話

會話是多個進程組的集合。

注意事項

創建會話不能是進程組組長,該進程變成新會話首進程。

創建新會話丟棄原有的控制終端,該會話沒有控制終端。

建立新會話時,先調用fork,父進程終止,子進程調用setsid()

getsid函數

獲取進程所屬的會話id

pid_t getsid(pid_t pid);
成功 返回會話id
失敗 -1
ps ajx命令查看系統中的進程

組長進程不能成為新會話首進程,新會話首進程必定會成為組長進程。?

setsid函數

創建會話,以自己的ID設置進程組ID,同時也是新會話的ID

pid_t setsid(void)
成功:返回調用進程的會話id;
失敗:-1

調用setsid函數的進程,既是新的會長,也是新的組長。

守護進程(daemon精靈,進程)

守護進程時Linux中的后臺服務進程,通常運行與操作系統后臺,脫離控制終端,一般不與用戶直接交互 , 周期性的等待某個事件發生或周期性執行某一動作,不受用戶登入注銷影響。一般使用d結尾的名字。

守護進程創建步驟:

1、fork子進程,讓父進程終止。

2、子進程調用setsid創建新會話。

3、通常根據需要,改變工作目錄位置,chdir() , 防止目錄被卸載

4、通常根據需要,重設置umask文件權限掩碼,影響新文件的創建權限

5、通常根據需要,關閉/重定向 文件描述符

6、守護進程 業務邏輯 while()

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<pthread.h>
#include<sys/stat.h>
#include<fcntl.h>
int main(int argc , char *argv[])
{pid_t pid ;int fd ;pid = fork();if(pid > 0){exit(0);   //正常終止父進程}else{pid = setsid();    //創建新會話if(pid == -1){perror("set error");exit(1);}int ret = chdir("/home/qqq");   //改變工作目錄位置if(ret == -1){perror("chdir error");exit(1);}umask(0022);   // 設置掩碼權限close(STDIN_FILENO);   // 關閉文件描述符fd = open ("/dev/null" , O_RDWR);if(fd == -1){perror("open error");exit(1);}dup2(fd , STDOUT_FILENO);   //重定向dup2(fd , STDERR_FILENO);while(1);  // 模擬守護進程做的事情}return 0 ;
}

這里由于我不明白為什么需要將標準輸入關閉,并且將標準輸出和標準錯誤重定向,我上網查了一些資料:

1、為什么要關閉STDIN_FILENO?
守護進程是在后臺運行的,不應該與終端交互,因此不需要標準輸入,為防止錯誤,直接關閉。

2、為什么要將STDOUT and STDERR? ?--->fd 0? ("/dev/null")

"/dev/null"是一個特殊設備,寫的什么東西進去都會被吃掉,讀取的時候什么也看不到,守護進程不應該輸出信息到終端,因此重定向給 fd(此時是 /dev/null)本質上就是為了干凈、不占資源、避免潛在錯誤。

線程(不要將線程和信號混合用)

線程 : LWP,light weight process 輕量級的進程 , 本質仍是進程(Linux環境下)

進程: 獨立的進程地址空間 , 有PCB

線程:有獨立的PCB,但沒有獨立的地址空間(共享)

Linux下 線程是最小的執行單位 , 進程是最小分配資源單位,可以看成只有一個線程的進程。

ps -Lf 進程id? --->線程號 LWP --->CPU執行的最小單位。

線程可以看作寄存器和棧的集合。

線程共享資源

文件描述符表 、 每種信號的處理方式 、 當前工作目錄 、 用戶ID和組ID 、 內存地址空間、全局變量

線程非共享資源

線程id 、 處理器現場和棧指針(內核棧) 、獨立的棧空間(用戶棧) 、 error變量 、 信號屏蔽字

線程的優缺點

優點:提高程序的并發性 ,?開銷小 ,?數據通信、共享數據方便

缺點:庫函數不穩定 , 調試、編寫困難、GDB不支持 , 對信號支持不友好

優點突出,缺點不明顯,能使用線程使用線程

線程控制原語

pthread_self函數

獲取線程ID ,注意這里的線程ID和線程號LWP不一樣。

線程id是在進程地址空間內部,用來表示線程身份id號

pthread_t pthread_self(void);
成功返回 線程id

pthread_create函數

int pthread_create(pthread_t * tid ,const pthread_attr_t *attr , void *(*start_rountn)(void*) , void *arg);pthread_t * tid:傳出參數,傳出創建子線程的id。
const pthread_attr_t *attr:線程屬性 , 傳NULL表示使用默認屬性。
void *(*start_rountn)(void*):子線程回調函數,創建成功,pthread_create()函數返回時,該回調函數                            會被自動調用。
void *arg:回調函數的參數,沒有的話使用NULL返回值 成功 0
失敗errno

循環創建5個子線程。?

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<pthread.h>void* func(void * arg)
{int i = (int) arg;printf("I am %dth child , pid:%d , tid:%lu\n" , i+1 , getpid() , pthread_self());return NULL;    
}int main(int argc , char* argv[])
{pthread_t tid;int i ,ret;for(i = 0 ; i < 5 ; i++){ret = pthread_create(&tid , NULL , func , (void*)i);if(ret == -1){perror("pthread_create error");exit(1);}    }sleep(i);printf("I am main , pid:%d , tid:%lu\n" , getpid() , pthread_self());return 0 ;    
}

pthread_exit函數

將當前線程退出。

void pthread_exit(void *retval);
retval:退出值。無退出值時,NULLexit() ; 退出當前進程
return ; 返回到調用者那里去
pthread_exit() ; 將調用該函數的線程退出

pthread_join函數

阻塞等待線程退出,獲取線程退出狀態。回收子線程。

int pthread_join(pthread_t thread, void **retval);
返回值 成功 0 
失敗 -1

pthread_cancel函數

殺死(取消)線程。相當于kill函數。但是需要取消點(保存點) 。如果子線程沒有到達取消點,那么該函數無效,我們可以在程序中手動添加一個取消點,使用pthread_testcancel()。成功被cancel函數殺死的進程,可以使用pthread_join回收。

int pthread_cancel(pthread_t thread);
返回值: 成功 0 
失敗 errno

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

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

相關文章

微信小程序拖拽排序有效果圖

效果圖 .wxml <view class"container" style"--w:{{w}}px;" wx:if"{{location.length}}"><view class"container-item" wx:for"{{list}}" wx:key"index" data-index"{{index}}"style"--…

hadoop三大組件的結構及各自的作用

1 HDFS 1.1功能 HDFS 是 Hadoop 的分布式文件系統&#xff0c;用于存儲和管理海量數據。它具有高容錯性、高吞吐量和可擴展性&#xff0c;能夠在多個節點上存儲和管理大規模數據 1.2架構&#xff1a;采用主從架構&#xff0c;由一個 NameNode 和多個 DataNode 組成。NameNode…

解決jupyter notebook修改路徑下沒有c.NotebookApp.notebook_dir【建議收藏】

文章目錄 一、檢查并解決問題二、重新設置默認路徑創作不易&#xff0c;感謝未來首富們的支持與關注&#xff01; 最近在用jupyter notebook編寫代碼時&#xff0c;更新了一下Scikit-learn的版本&#xff0c;然后重新打開jupyter notebook的時候&#xff0c;我傻眼了&#xff0…

MCP Host、MCP Client、MCP Server全流程實戰

目錄 準備工作 MCP Server 實現 調試工作 MCP Client 實現 MCP Host 配置 第一步:配置支持 function calling的 LLM 第二步:添加MCP Server 一般有兩種方式,第一種json配置,第二種直接是Command形式,我這里采用Command形式 第三步:使用MCP Server 準備工作 安裝…

4.21—4.22學習總結 JavaWeb:HTML-CSS

Web&#xff1a;能夠通過瀏覽器訪問到的網站。 Web標準&#xff1a; HTML&#xff1a; vscode中進行注釋的快捷鍵為ctrl斜線/ h1的字體最大&#xff0c;依次遞減&#xff0c;只存在h1—h6。 超鏈接&#xff1a; 設置字體顏色&#xff1a; 方式三寫一個css文件&#xff0c;將方…

Kaamel Agent: 基于EU AI Act的AI影響評估(AIIA)

1. 引言&#xff1a;安全視角下的AI監管 隨著人工智能技術的快速發展和廣泛應用&#xff0c;AI系統在為社會帶來創新和效率的同時&#xff0c;也引發了諸多關于安全、隱私和合規的擔憂。在這一背景下&#xff0c;全球范圍內涌現出多種監管框架和標準&#xff0c;旨在確保AI系統…

Mongodb分布式文件存儲數據庫

文章目錄 一、MongoDB 簡介基本信息特點內部組件 二、MongoDB 部署1. 安裝依賴2. 解壓部署并配置環境變量3. 修改配置文件以及啟動服務4.數據庫權限管理 三、MongoDB 管理1. 角色權限2. 操作命令用戶管理命令常用命令&#xff08;Mongo4.2.8&#xff09;數據庫相關用戶相關集合…

麒麟V10安裝MySQL8.4

1、下載安裝包 wget https://cdn.mysql.com//Downloads/MySQL-8.4/mysql-8.4.5-1.el7.x86_64.rpm-bundle.tar2、解壓 mkdir -p /opt/mysql tar -xvf mysql-8.4.5-1.el7.x86_64.rpm-bundle.tar -C /opt/mysql3、安裝MySQL 3.1、卸載mariadb rpm -qa | grep mariadb rpm -e m…

Unreal如何使用后處理材質實現一個黑屏漸變效果

文章目錄 前言相機后期處理材質創建材質相機設置動態修改FadeAlpha參數使用示例最后前言 UE5 開發VR ,如何通過PostProcess輕松實現黑屏漸變效果 最簡單的辦法,其實是使用一個半球形模型,遮擋住相機,然后控制這個半球形遮罩的顏色透明度,至少Unity中默認的Tunneling是這么…

其它生成式(對比列表生成式)

一、字典生成式&#xff1a; # keys[name, age, gender] # dic{key:None for key in keys} # print(dic) items[(name, Tom), (age, 18), (gender, male)] res{k:v for k,v in items if k ! gender} print(res) 二、集合生成式&#xff1a; keys[name, age, gender] set1{ke…

健身房管理系統(springboot+ssm+vue+mysql)含運行文檔

健身房管理系統(springbootssmvuemysql)含運行文檔 健身房管理系統是一個全面的解決方案&#xff0c;旨在幫助健身房高效管理其運營。系統提供多種功能模塊&#xff0c;包括會員管理、員工管理、會員卡管理、教練信息管理、解聘管理、健身項目管理、指導項目管理、健身器材管理…

LeetCode 第 262 題全解析:從 SQL 到 Swift 的數據分析實戰

文章目錄 摘要描述題解答案&#xff08;SQL&#xff09;Swift 題解代碼分析代碼示例&#xff08;可運行 Demo&#xff09;示例測試及結果時間復雜度分析空間復雜度分析總結未來展望 摘要 在實際業務中&#xff0c;打車平臺要監控行程的取消率&#xff0c;及時識別服務質量的問…

三生原理與現有密碼學的核心區別?

AI輔助創作&#xff1a; 三生原理與現有密碼學的核心區別 一、?哲學基礎與設計邏輯? ?動態生成 vs 靜態分析? 三生原理以“陰陽動態平衡”為核心&#xff0c;通過參數化生成&#xff08;如素數構造中的陰陽元聯動公式&#xff09;模擬系統演化過程&#xff0c;而現有密碼…

4.19-4.20學習總結 網絡編程+反射+動態代理

網絡編程&#xff1a; IPv6有2的128次方個ip。 端口號&#xff1a; 協議&#xff1a; UDP發送和接收消息&#xff1a; UDP的三種通信方式&#xff1a; 單播&#xff1a;一對一&#xff0c;一個發送端對應一個接收端 創建DatagramSocket對象 組播&#xff1a;一個發送端對應一…

Swiper、樣式結構重用、GridGridItem

今日核心&#xff1a; 容器組件&#xff1a;Swiper、Grid\GridItem樣式&結構重用&#xff1a;Builder、Extend、Styles 相關資源: 圖片素材&#xff1a;&#x1f4ce;day01.zip 1. Swiper 1.1. 適用場景 首先來看看 Swiper 在什么情況下會用到 鏈接 Swiper組件提供滑…

前沿分享|技術雷達202504月刊精華

本期雷達 ###技術部分 7. GraphRAG 試驗 在上次關于 檢索增強生成&#xff08;RAG&#xff09;的更新中&#xff0c;我們已經介紹了GraphRAG。它最初在微軟的文章中被描述為一個兩步的流程&#xff1a; &#xff08;1&#xff09;對文檔進行分塊&#xff0c;并使用基于大語言…

數據結構與算法-順序表應用

一.通訊錄的創建 首先我們要理解的是通訊錄本身就是以順序表為底層的 只不過順序表中的數組&#xff0c;這里我們是用結構體來替代&#xff0c;用來存儲用戶的信息 由于是通訊錄的本質就是順序表&#xff0c;所以順序表的任何方法它都能套用 Contact.h: #pragma once #def…

【C++】新手入門指南(下)

文章目錄 前言 一、引用 1.引用的概念和定義 2.引用的特性 3.引用的使用 4.const引用 5.指針和引用的關系 二、內聯函數 三、nullptr 總結 前言 這篇續上篇的內容新手入門指南&#xff08;上&#xff09;&#xff0c;繼續帶大家學習新知識。如果你感興趣歡迎訂購本專欄。 一、…

uniapp-商城-33-shop 布局搜索頁面以及u-search

shop頁面上有一個搜索&#xff0c;可以進行商品搜索&#xff0c;這里我們先做一個頁面布局&#xff0c;后面再來進行數據i聯動。 1、shop頁面的搜索 2、搜索的頁面代碼 <navigator class"searchView" url"/pagesub/pageshop/search/search"> …

SAP 采購訂單如何防止開票數量 大于 收貨數量呢

配置點如下&#xff1a; 事務碼&#xff1a;OMRM&#xff0c;配置如下 當過賬開票的數量 大于收貨數量的時候會提示如下&#xff1a;