【C語言】多進程/多線程

【C語言】多進程/多線程

  • 參考鏈接
  • 多進程/多線程服務器
    • 1. 多進程服務器
    • 2. 多線程服務器
  • 結語
  • 參考鏈接

在這里插入圖片描述

參考鏈接

c 中文網
菜鳥 c

多進程/多線程服務器

??多進程和多線程是常用的并發編程技術。它們都允許程序同時執行多個任務,提高了系統的資源利用率和程序的運行效率。

1. 多進程服務器

??多進程是指在操作系統中同時運行多個獨立的進程。每個進程都有自己獨立的地址空間和資源,進程間的通信通過操作系統提供的進程間通信機制進行。多進程可以充分利用多核處理器的優勢,提高系統的整體性能。然而,進程間的切換會引入較大的開銷,并且需要較高的內存開銷。

??服務器使用 fork 創建子進程來和客戶端進行通信,父進程負責取出連接請求。

#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <strings.h>
#include <string.h>
#include <ctype.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <arpa/inet.h>// 信號處理函數
void waitchild(int signo)
{pid_t wpid;while (1){wpid = waitpid(-1, NULL, WNOHANG);if (wpid > 0){printf("child exit, wpid==[%d]\n", wpid);}else if (wpid == 0 || wpid == -1){break;}}
}int main()
{// 阻塞SIGCHLD信號sigset_t mask;sigemptyset(&mask);sigaddset(&mask, SIGCHLD);sigprocmask(SIG_BLOCK, &mask, NULL);int sigbol = 1;int sfd = socket(AF_INET, SOCK_STREAM, 0);// 設置端口復用int opt = 1;setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int));struct sockaddr_in soaddr;bzero(&soaddr, sizeof(soaddr));soaddr.sin_family = AF_INET;soaddr.sin_port = htons(9999);soaddr.sin_addr.s_addr = htonl(INADDR_ANY);bind(sfd, (struct sockaddr *)&soaddr, sizeof(soaddr));//監聽-listenlisten(sfd, 128);struct sockaddr_in clientsocket;socklen_t clilen;char sIP[16];while (1){clilen = sizeof(clientsocket);bzero(&clientsocket, clilen);int cfd = accept(sfd, (struct sockaddr *)&clientsocket, &clilen);/* */int pid = fork();if (pid == 0){// 子進程close(sfd);char buff[64];printf("current pid is [%d],father is [%d]\n", getpid(), getppid());while (1){memset(buff, 0x00, sizeof(buff));int n = read(cfd, buff, sizeof(buff));if (n == 0){return 0;}else if (n < 0){perror("child read error");return -1;}printf("child [%d] recv data from [%s:%d]:[%s]\n", getpid(), inet_ntop(AF_INET, &clientsocket.sin_addr.s_addr, sIP, sizeof(sIP)), ntohs(clientsocket.sin_port), buff);for (int i = 0; i < n; i++){buff[i] = toupper(buff[i]);}n = Write(cfd, buff, n);if (n <= 0){perror("child write error");return -1;}}}else if (pid > 0){// 父進程close(cfd);//假如是初次fork子進程,那么才注冊信號處理函數if (sigbol == 1){sigbol = 0;// 注冊SIGCHLD信號處理函數struct sigaction act;act.sa_handler = waitchild;act.sa_flags = 0;sigemptyset(&act.sa_mask);sigaction(SIGCHLD, &act, NULL);// 解除對SIGCHLD信號的阻塞sigprocmask(SIG_UNBLOCK, &mask, NULL);}//循環等待下一個連接請求的到來continue;}else{perror("fork error");close(sfd);return -1;}}return 0;
}

2. 多線程服務器

??多線程是指在同一個進程中同時運行多個獨立的線程。與進程不同,線程共享同一個地址空間和資源,可以通過共享內存等方式進行線程間的通信。多線程可以減少線程間的切換開銷和內存開銷,提高系統的響應速度和資源利用率。然而,多線程編程需要考慮線程安全問題,需要使用線程同步技術來保證共享資源的正確訪問。

??主線程創建子線程,用子進程和客戶端通信。

#include <arpa/inet.h>
#include <pthread.h>
#include <strings.h>
#include <string.h>
#include <ctype.h>
#include <arpa/inet.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <unistd.h>typedef struct info
{int cfd; // 若為-1表示可用, 大于0表示已被占用int idx;pthread_t thread;          // 由pthread_create 返回struct sockaddr_in client; // 由accept 返回
} INFO;INFO thInfo[1024];void initThreadArr()
{for (int i = 0; i < 1024; i++){bzero(&thInfo[i],sizeof(thInfo[i]));thInfo[i].cfd = -1;}
}int findIndex()
{int i;for (i = 0; i < 1024; i++){if (thInfo[i].cfd == -1){return i;}}//if (i == 1024)//{//    return -1;//}return -1;
}void *threadFunc(void *arg)
{INFO *curthread = (INFO *)arg;char sIP[16];printf("current thread id [%ld],arr index is [%d],cfd is [%d],client ip is [%s:%d]\n", pthread_self(), curthread->idx, curthread->cfd, inet_ntop(AF_INET, &curthread->client.sin_addr.s_addr, sIP, sizeof(sIP)), ntohs(curthread->client.sin_port));char buff[64];while (1){memset(buff, 0x00, sizeof(buff));int n = read(curthread->cfd, buff, sizeof(buff));if (n == 0){bzero(&thInfo[curthread->idx],sizeof(thInfo[curthread->idx]));thInfo[thInfo->idx].cfd = -1;return 0;}else if (n < 0){bzero(&thInfo[curthread->idx],sizeof(thInfo[curthread->idx]));thInfo[thInfo->idx].cfd = -1;perror("child read error");return 0;}printf("child thread [%ld] recv data from [%s:%d]:[%s]\n", pthread_self(), inet_ntop(AF_INET, &curthread->client.sin_addr.s_addr, sIP, sizeof(sIP)), ntohs(curthread->client.sin_port), buff);for (int i = 0; i < n; i++){buff[i] = toupper(buff[i]);}n = write(curthread->cfd, buff, n);if (n <= 0){bzero(&thInfo[curthread->idx],sizeof(thInfo[curthread->idx]));thInfo[thInfo->idx].cfd = -1;perror("child write error");return 0;}}
}int main()
{initThreadArr();int sfd = socket(AF_INET, SOCK_STREAM, 0);// 設置端口復用int opt = 1;setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int));struct sockaddr_in soaddr;bzero(&soaddr, sizeof(soaddr));soaddr.sin_family = AF_INET;soaddr.sin_port = htons(9999);soaddr.sin_addr.s_addr = htonl(INADDR_ANY);bind(sfd, (struct sockaddr *)&soaddr, sizeof(soaddr));// 監聽-listenlisten(sfd, 128);struct sockaddr_in clientsocket;socklen_t clilen;int cfd;int index;int ret;while (1){index = -1;clilen = sizeof(clientsocket);bzero(&clientsocket, clilen);cfd = accept(sfd, (struct sockaddr *)&clientsocket, &clilen);// 從線程數組中找一個可以用的index = findIndex();thInfo[index].idx = index;thInfo[index].client = clientsocket;thInfo[index].cfd = cfd;// 創建線程ret = pthread_create(&thInfo[index].thread, NULL, threadFunc, &thInfo[index]);if (ret != 0){printf("create thread error:[%s]\n", strerror(ret));exit(-1);}// 設置子線程為分離屬性pthread_detach(thInfo[index].thread);}Close(sfd);return 0;
}

結語

??多進程和多線程的選擇取決于具體的應用場景。如果任務之間需要較高的隔離度,或者需要充分利用多核處理器的優勢,可以選擇多進程。如果任務之間需要較低的切換開銷和內存開銷,或者需要提高系統的響應速度和資源利用率,可以選擇多線程。

參考鏈接

c 中文網
菜鳥 c

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

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

相關文章

mysql 磐維(opengauss)tidb誤刪數據之高級恢復

Mysql參考&#xff1a; Mysql 8.0 XtraBackupMysqlbinlog 完全恢復 - 墨天輪 Mysql 8.0 XtraBackupMysqlbinlog 完全恢復[TOC]# 一、安裝mysql 8.0.19## 1.1https://www.modb.pro/db/509223MySQL 的全量備份、增量備份與 Binlog 時間點恢復_mysqlbinlog自動備份嗎-CSDN博客文章…

3. 軸指令(omron 機器自動化控制器)——>MC_SetPosition

機器自動化控制器——第三章 軸指令 11 MC_SetPosition變量?輸入變量?輸出變量?輸入輸出變量 功能說明?時序圖?重啟動運動指令?多重啟運動指令?異常 MC_SetPosition 將軸的指令當前位置和反饋當前位置變更為任意值。 指令名稱FB/FUN圖形表現ST表現MC_SetPosition當前位…

從 @SpringBootApplication 出發,深度剖析 Spring Boot 自動裝配原理

在 Spring Boot 的開發旅程中&#xff0c;SpringBootApplication 注解堪稱開啟便捷開發之門的鑰匙。它不僅是一個簡單的注解&#xff0c;更是理解 Spring Boot 自動裝配原理的重要入口。接下來&#xff0c;我們將以SpringBootApplication 為切入點&#xff0c;深入探究 Spring …

MySQL面試專題

1.什么是BufferPool&#xff1f; Buffer Pool基本概念 Buffer Pool&#xff1a;緩沖池&#xff0c;簡稱BP。其作用是用來緩存表數據與索引數據&#xff0c;減少磁盤IO操作&#xff0c;提升效率。 Buffer Pool由緩存數據頁(Page) 和 對緩存數據頁進行描述的控制塊 組成, 控制…

調用百度api實現語音識別(python)

該代碼實現了一個企業級的語音識別解決方案,通過調用百度語音識別API,實現實時錄音識別和對已有音頻語音識別功能。 百度智能云:請自行訪問百度智能云,開通免費的語音識別功能,獲取API_KEY和SECRET_KEY。操作按照百度流程即可,可免費申請。 首先,配置下百度API和描述下錯…

KRaft模式

目錄標題 Kraft模式**1. 什么是Kraft模式&#xff1f;****2. 為什么引入Kraft模式&#xff1f;****3. 核心優勢****4. 架構與工作原理****5. 部署與配置要點****6. 適用場景與最佳實踐****總結**KIP-833: Mark KRaft as Production Ready除了Kraft模式&#xff0c;Kafka還有以下…

單片機電路中常見的英文術語及縮寫

以下是單片機電路中常見的英文術語及縮寫的解釋及其作用說明&#xff0c;按功能分類整理&#xff0c;便于理解&#xff1a; 一、核心術語 MCU (Microcontroller Unit) ? 中文&#xff1a;微控制器單元 ? 作用&#xff1a;單片機的核心芯片&#xff0c;集成CPU、存儲器、外設接…

常見框架漏洞之一:Thinkphp5x

ThinkPHP是為了簡化企業級應?開發和敏捷WEB應?開發?誕?的&#xff0c;是?個快速、兼容?且簡單的輕量級國產PHP開發框架&#xff0c;誕?于2006年初&#xff0c;原名FCS&#xff0c;2007年元旦正式更名為 ThinkPHP&#xff0c;遵循Apache2開源協議發布&#xff0c;從Stru…

2025年優化算法:龍卷風優化算法(Tornado optimizer with Coriolis force,TOC)

龍卷風優化算法&#xff08;Tornado optimizer with Coriolis force&#xff09;是發表在中科院二區期刊“ARTIFICIAL INTELLIGENCE REVIEW”&#xff08;IF&#xff1a;11.7&#xff09;的2025年智能優化算法 01.引言 當自然界的狂暴之力&#xff0c;化身數字世界的智慧引擎&…

面試中如何回答性能優化的問題

性能問題和Bug不同,后者的分析和解決思路更清晰,很多時候從應用日志(文中的應用指分布式服務下的單個節點)即可直接找到問題根源,而性能問題,其排查思路更為復雜一些。 對應用進行性能優化,是一個系統性的工程,對工程師的技術廣度和技術深度都有所要求。一個簡單的應用…

CMake 函數和宏

CMake 函數 CMake 函數定義語法如下, 其中 name 為函數名, <arg1> 為參數名, <commands> 為函數體. 函數定義后, 可以通過 name 調用函數. 函數名允許字母數字下劃線, 不區分大小寫. function(name [<arg1> ...])<commands> endfunction()如下的樣例…

【QA】Qt有哪些迭代器模式的應用?

在 Qt/C 中&#xff0c;迭代器模式的設計主要分為 標準 C 風格 和 Qt 框架特有風格&#xff0c;以下結合代碼詳細說明兩種實現方式的關鍵設計及其應用場景&#xff1a; 一、Qt 框架中的迭代器模式設計 Qt 提供了兩種迭代器風格&#xff1a;Java 風格&#xff08;顯式迭代器&am…

Mysql表的簡單操作

&#x1f3dd;?專欄&#xff1a;Mysql_貓咪-9527的博客-CSDN博客 &#x1f305;主頁&#xff1a;貓咪-9527-CSDN博客 “欲窮千里目&#xff0c;更上一層樓。會當凌絕頂&#xff0c;一覽眾山小。” 目錄 3.1 創建表 3.2 查看表結構 3.3 修改表 1. 添加字段 2. 修改字段 3…

【云馨AI-大模型】自動化部署Dify 1.1.2,無需科學上網,Linux環境輕松實現,附Docker離線安裝等

Dify介紹 官網&#xff1a;https://dify.ai/zh生成式 AI 應用創新引擎開源的 LLM 應用開發平臺。提供從 Agent 構建到 AI workflow 編排、RAG 檢索、模型管理等能力&#xff0c;輕松構建和運營生成式 AI 原生應用。 Dify安裝腳本 目錄創建 mkdir -p /data/yunxinai &&a…

WordPress上傳圖片時顯示“未提供數據”錯誤

在WordPress中上傳圖片時顯示“未提供數據”的錯誤&#xff0c;通常是由多種原因引起的&#xff0c;以下是一些常見的問題及其解決方法&#xff1a; 1. 文件權限問題 WordPress需要正確的文件和目錄權限才能正常上傳圖片。如果權限設置不正確&#xff0c;可能會導致無法上傳圖…

python3面試題20個(python web篇)

更多內容請見: python3案例和總結-專欄介紹和目錄 文章目錄 1.python asyncio的原理?2.對Flask藍圖(Blueprint)的理解?3.Flask 和 Django 路由映射的區別?4.什么是wsgi,uwsgi,uWSGI?5.Django、Flask、Tornado的對比?6.CORS 和 CSRF的區別?7.Session,Cookie,JWT的理解8.簡…

RedisTemplate和RedissonClient適用的場景有什么不同

在 Spring Boot 項目中&#xff0c;RedisTemplate 和 RedissonClient 分別針對不同的使用場景設計&#xff0c;以下是它們的核心區別和適用場景分析&#xff1a; 一、RedisTemplate&#xff08;Spring Data Redis&#xff09; 定位 Spring 官方提供的 Redis 操作工具&#xf…

人臉表情識別系統分享(基于深度學習+OpenCV+PyQt5)

最近終于把畢業大論文忙完了&#xff0c;眾所周知碩士大論文需要有三個工作點&#xff0c;表情識別領域的第三個工作點一般是做一個表情識別系統出來&#xff0c;如下圖所示。 這里分享一下這個表情識別系統&#xff1a; 采用 深度學習OpenCVPyQt5 構建&#xff0c;主要功能包…

GitHub供應鏈攻擊事件:Coinbase遭襲,218個倉庫暴露,CI/CD密鑰泄露

此次供應鏈攻擊涉及GitHub Action "tj-actions/changed-files"&#xff0c;最初是針對Coinbase的一個開源項目的高度定向攻擊&#xff0c;隨后演變為范圍更廣的威脅。 攻擊過程與影響 Palo Alto Networks Unit 42在一份報告中指出&#xff1a;“攻擊載荷主要針對其…

Redis 核心源碼解析:從設計哲學到企業級應用實踐

一、Redis 的核心設計哲學 Redis 的成功源于其 「用內存換時間」 的核心理念&#xff0c;圍繞以下三個核心原則構建&#xff1a; 極簡主義&#xff1a;單線程模型避免鎖競爭&#xff0c;代碼保持高度內聚。 性能至上&#xff1a;所有數據常駐內存&#xff0c;網絡層采用事件驅…