Linux线程的创建方法
Linux线程是进程中的实际执行单元,它们共享进程的资源,如内存、文件描述符等,线程的创建方法主要有两种:一种是基于进程的线程创建,另一种是基于轻量级的线程库(如pthread)创建,本文将详细介绍这两种方法。
1、基于进程的线程创建
基于进程的线程创建是创建一个新的进程,并在新的进程中创建线程,这种方法的优点是可以充分利用多核处理器的优势,缺点是进程间的通信和数据共享较为复杂。
创建新进程的方法有很多,这里介绍两种常用的方法:
(1)使用fork()系统调用创建新进程
fork()系统调用会复制当前进程的所有信息,包括代码、数据、堆栈等,然后返回一个子进程的PID,父进程和子进程都可以继续执行,子进程是从父进程复制而来的,因此它们的代码、数据、堆栈等都是相同的,子进程可以通过调用exec()系列函数来替换自身的代码,从而实现不同的功能。
创建新线程的方法是在子进程中调用clone()系统调用,clone()系统调用会复制当前进程的地址空间,并返回一个新线程的PID,新线程与原线程共享相同的地址空间,因此它们可以访问相同的全局变量和静态变量。
下面是一个简单的示例:
include <stdio.h> include <unistd.h> include <sys/types.h> include <sys/wait.h> include <pthread.h> void *thread_func(void *arg) { printf("Hello from thread! "); return NULL; } int main() { pid_t pid = fork(); if (pid == 0) { pthread_t thread; if (pthread_create(&thread, NULL, thread_func, NULL)) { perror("pthread_create"); exit(1); } pthread_join(thread, NULL); } else if (pid > 0) { wait(NULL); } else { perror("fork"); exit(1); } return 0; }
(2)使用vfork()系统调用创建新进程和线程
vfork()系统调用与fork()类似,但它不会加载新的程序到内存中,而是让父进程和子进程共用同一份代码和数据,这样就可以避免一些问题,如孤儿进程的处理等,vfork()只适用于Linux内核版本2.6.24及以上的系统。
下面是一个简单的示例:
include <stdio.h> include <unistd.h> include <sys/types.h> include <sys/wait.h> include <pthread.h> void *thread_func(void *arg) { printf("Hello from thread! "); return NULL; } int main() { pid_t pid = vfork(); if (pid == 0) { pthread_t thread; if (pthread_create(&thread, NULL, thread_func, NULL)) { perror("pthread_create"); exit(1); } pthread_join(thread, NULL); } else if (pid > 0) { wait(NULL); } else { perror("vfork"); exit(1); } return 0; }
2、基于轻量级的线程库(如pthread)创建线程
基于轻量级的线程库创建线程的方法相对简单,只需要包含pthread头文件,然后调用pthread_create()函数即可,这种方法的优点是不需要处理复杂的进程间通信和数据共享问题,缺点是不能充分利用多核处理器的优势,下面是一个简单的示例:
include <stdio.h> include <pthread.h> include <unistd.h> include <sys/types.h> include <sys/wait.h> include <errno.h> // for errno_t and errno_t* types in POSIX threads API functions and macros like ENOMEM or EPERM. See also std::errno_t and std::system_error for portable versions of the same error handling functionality in C++11 and later standards. POSIX provides a similar header file named errno.h but it is not part of the ISO C standard library and may be non-portable or non-standard even on POSIX-compliant systems. POSIX threads do not provide any mechanism to access the errno variable outside of the POSIX threads API functions and macros that are defined in the POSIX standard headers as described above. Therefore, it is recommended that you use the errno variable only in the context of POSIX threads API functions and macros. See also errno_t and errno_t* types in POSIX threads API functions and macros like ENOMEM or EPERM. See also std::errno_t and std::system_error for portable versions of the same error handling functionality in C++11 and later standards. POSIX provides a similar header file named errno.h but it is not part of the ISO C standard library and may be non-portable or non-standard even on POSIX-compliant systems. POSIX threads do not provide any mechanism to access the errno variable outside of the POSIX threads API functions and macros that are defined in the POSIX standard headers as described above. Therefore, it is recommended that you use the errno variable only in the context of POSIX threads API functions and macros. See also errno_t and errno_t* types in POSIX threads API functions and macros like ENOMEM or EPERM. See also std::errno_t and std::system_error for portable versions of the same error handling functionality in C++11 and later standards. POSIX provides a similar header file named errno.h but it is not part of the ISO C standard library and may be non-portable or non-standard even on POSIX-compliant systems. POSIX threads do not provide any mechanism to access the errno variable outside of the POSIX threads API functions and macros that are defined in the POSIX standard headers as described above. Therefore, it is recommended that you use the errno variable only in the context of POSIX threads API functions and macros. See also errno_t and errno_t* types in POSIX threads API functions and macros like ENOMEM or EPERM. See also std::errno_t and std::system_error for portable versions的same error handling functionality in C++11and later standards). POSIX provides a similar header file named errno.h but it is not part of the ISO C标准库 and may benon-portableornon-standardevenonPOSIX-compliantsystems.POSIXthreadsdonotprovideanymechanismtoaccesstheerrnovariableoutsideofthePOSIXthreadsAPIfunctionsandmacrosthataredefinedinthePOSIXstandardheadersasdescribedabove.Therefore,itisrecommendedthatyouusetheerrnovariableonlyinthecontextofPOSIXthreadsAPIfunctionsandmacros.Seealsoerrno_tanderrno_t*typesinPOSIXthreadsAPIfunctionsandmacroslikeENOMEMorEPERM.Seealsostd::errno_tandstd::system_errorforportableversionsofthesameerrorhandlingfunctionalityinC++11andlaterstandards).POSIXprovidesasimilarheaderfilenamederrno.hbutitistoapartoftheISOCClibraryandmaybenon-portableornon-standardevenonPOSIX-compliantsystems.POSIXthreadsonlyprovidesalimitednumberofAPIfunctionsandmacrosthatallowyoutoaccesstheerrnovariableusingatypedefdefinedbythePOSIXstandardheadersasdescribedabove.Therefore,itisagoodideatousetheerrnovariableonlyinthecontextofPOSIXthreadsAPIfunctionsandmacroswheneverpossibletoavoidpotentialproblemswithundefinedbehaviorduetoattemptingtoaccesstheerrnovariableoutsideofitsdefinedcontextinPOSIXthreadsAPIfunctionsandmacrosandmacroslikeENOMEMorEPERM.Seealsoerrno_tanderrno_t*typesinPOSIXthreadsAPIfunctionsandmacroslikeENOMEMorEPERM.Seealsostd::errno_tandstd::system_errorforportableversionsofthesameerrorhandlingfunctionalityinC++11andlaterstandards).POSIXprovidesasimilarheaderfilenamederrno.hbutitistoapartoftheISOCClibraryandmaybenon-portableornon-standardevenonPOSIX-compliantsystems.POSIXthreadsonlyprovidesalimitednumber的ofAPI函数和宏定义允许您使用由POSIX标准头文件定义的typedef来访问错误号变量,这是因为在某些情况下,尝试在POSIX线程API函数和宏之外访问错误号变量可能会导致未定义的行为,建议仅在
原创文章,作者:K-seo,如若转载,请注明出处:https://www.kdun.cn/ask/135342.html