1.fork()Դ?源码?
2.nginx源码分析--master和worker进程模型
3.剖析Linux内核源码解读之《实现fork研究(一)》
4.剖析Linux内核源码解读之《实现fork研究(二)》
5.fork的是什么意思?
6.cloneåforkè°ç¨çåºå«åèç³»
fork()Դ??
在Github上,获取并利用开源代码进行本地二次开发是源码一项常见操作。首先,源码你需要通过Fork功能复制一个大佬的源码开源代码仓库,这就像克隆一个项目,源码让你可以在不影响原始项目的源码不要窗口按钮突破源码情况下进行试验或贡献代码。要实现这一点,源码只需简单地执行两个步骤:
1. Fork仓库:复制链接后,源码使用git clone命令,源码将仓库克隆到本地,源码例如:`git clone /YOUR-USERNAME/origin-repo.git`
2. 同步本地副本:为保持与原始仓库同步,源码你需要配置git。源码通常,源码这涉及设置upstream指向主仓库,源码然后使用git pull从upstream获取更新。源码如果你想将这些更改推送到你的Fork仓库,还需要执行一次`git push`操作。修改pptp源码再安装
通过这些步骤,你就可以在本地对Fork的源代码进行修改,并确保与原始代码库保持同步。这是开源社区中协作开发的基础实践,帮助开发者们扩展和改进现有的开源项目。
nginx源码分析--master和worker进程模型
一、Nginx整体架构
正常执行中的nginx会有多个进程,其中最基本的是master process(主进程)和worker process(工作进程),还可能包括cache相关进程。
二、核心进程模型
启动nginx的主进程将充当监控进程,主进程通过fork()产生的子进程则充当工作进程。
Nginx也支持单进程模型,此时主进程即是工作进程,不包含监控进程。
核心进程模型框图如下:
master进程
监控进程作为整个进程组与用户的开源的博客系统源码交互接口,负责监护进程,不处理网络事件,不负责业务执行,仅通过管理worker进程实现重启服务、平滑升级、更换日志文件、配置文件实时生效等功能。
master进程通过sigsuspend()函数调用大部分时间处于挂起状态,直到接收到信号。
master进程通过检查7个标志位来决定ngx_master_process_cycle方法的运行:
sig_atomic_t ngx_reap;
sig_atomic_t ngx_terminate;
sig_atomic_t ngx_quit;
sig_atomic_t ngx_reconfigure;
sig_atomic_t ngx_reopen;
sig_atomic_t ngx_change_binary;
sig_atomic_t ngx_noaccept;
进程中接收到的信号对Nginx框架的意义:
还有一个标志位:ngx_restart,仅在master工作流程中作为标志位使用,与信号无关。
核心代码(ngx_process_cycle.c):
ngx_start_worker_processes函数:
worker进程
worker进程主要负责具体任务逻辑,主要关注与客户端或后端真实服务器之间的数据可读/可写等I/O交互事件,因此工作进程的阻塞点在select()、epoll_wait()等I/O多路复用函数调用处,webview播放器源码等待数据可读/写事件。也可能被新收到的进程信号中断。
master进程如何通知worker进程进行某些工作?采用的是信号。
当收到信号时,信号处理函数ngx_signal_handler()会执行。
对于worker进程的工作方法ngx_worker_process_cycle,它主要关注4个全局标志位:
sig_atomic_t ngx_terminate;//强制关闭进程
sig_atomic_t ngx_quit;//优雅地关闭进程(有唯一一段代码会设置它,就是接受到QUIT信号。ngx_quit只有在首次设置为1时,才会将ngx_exiting置为1)
ngx_uint_t ngx_exiting;//退出进程标志位
sig_atomic_t ngx_reopen;//重新打开所有文件
其中ngx_terminate、ngx_quit、ngx_reopen都将由ngx_signal_handler根据接收到的信号来设置。ngx_exiting标志位仅由ngx_worker_cycle方法在退出时作为标志位使用。
核心代码(ngx_process_cycle.c):
剖析Linux内核源码解读之《实现fork研究(一)》
Linux内核源码解析:深入探讨fork函数的实现机制(一)
首先,我们关注的焦点是fork函数,它是草根源码社区石榴Linux系统创建新进程的核心手段。本文将深入剖析从用户空间应用程序调用glibc库,直至内核层面的具体过程。这里假设硬件平台为ARM,使用Linux内核3..3和glibc库2.版本。这些版本的库和内核代码可以从ftp.gnu.org获取。
在glibc层面,针对不同CPU架构,进入内核的步骤有所不同。当glibc准备调用kernel时,它会将参数放入寄存器,通过软中断(SWI) 0x0指令进入保护模式,最终转至系统调用表。在arm平台上,系统调用表的结构如下:
系统调用表中的CALL(sys_clone)宏被展开后,会将sys_clone函数的地址放入pc寄存器,这个函数实际由SYSCALL_DEFINEx定义。在do_fork函数中,关键步骤包括了对父进程和子进程的跟踪,以及对子进程进行初始化,包括内存分配和vfork处理等。
总的来说,调用流程是这样的:应用程序通过软中断触发内核处理,通过系统调用表选择并执行sys_clone,然后调用do_fork函数进行具体的进程创建操作。do_fork后续会涉及到copy_process函数,这个函数是理解fork核心逻辑的重要入口,包含了丰富的内核知识。在后续的内容中,我将深入剖析copy_process函数的工作原理。
剖析Linux内核源码解读之《实现fork研究(二)》
本文深入剖析了Linux内核源码中fork实现的核心过程,重点在于copy_process函数的解析。在Linux系统中,应用层可以通过fork创建子进程或子线程,而内核并不区分两者,它们共享相同的task_struct结构,用于描述进程或线程的状态、资源等。task_struct包含了进程或线程所有关键数据结构,如内存描述符、文件描述符、信号处理等,是内核调度程序识别和管理进程的重要依据。
copy_process作为fork实现的关键,其主要任务是初始化task_struct结构,分配新进程的PID,并将其加入到运行队列。这个过程中,内核栈的初始化导致了fork()调用的两次返回值不同,这与copy_thread函数中父进程复制内核栈至子进程并清零寄存器值有关。这样,子进程返回0,而父进程继续执行copy_thread后续操作,最后返回子进程的PID。
对于线程的独有和共享资源,独有资源通常包括线程特定的数据结构和状态,而共享资源则涉及父进程与线程间的共享内存、文件描述符和信号处理等。这些资源的管理对于多线程程序的正确运行至关重要,需确保线程间资源的互斥访问和安全共享。
fork的是什么意思?
在计算机术语中,fork是指创建一个子进程。它是由父进程复制自己的一份完全拷贝,然后在该拷贝上继续运行。子进程独立于原始进程,它有自己的进程ID,并且执行不同的程序段。通过fork,父进程可以将任务分配给子进程,从而实现并行处理。
另外,fork也是指复制一个源代码库,创建一个全新的代码库。这个新的代码库是原始代码库的副本,并且独立于原始代码库。程序员可以通过对这个新库进行修改和实验,同时不影响原始代码。这是一种很常见的开发方法,可以帮助程序员更好地管理代码。
在开源社区当中,fork还常常指代一种特殊的社交行为。开源项目通常是公开的,这意味着任何人都可以查看和使用它。如果某个人想要修改项目的代码,却不希望对原始项目代码造成破坏,那么可以使用fork。这个人可以将原始项目复制到自己的GitHub账户下,并创建一个独立的branch进行修改和实验。如果他的修改被证明是有价值的,那么他就可以通过pull request将修改并入原始项目。
cloneåforkè°ç¨çåºå«åèç³»
å¨Linuxä¸ä¸»è¦æä¾äºforkãvforkãcloneä¸ä¸ªè¿ç¨å建æ¹æ³ã
é®é¢
å¨linuxæºç ä¸è¿ä¸ä¸ªè°ç¨çæ§è¡è¿ç¨æ¯æ§è¡fork(),vfork(),clone()æ¶ï¼éè¿ä¸ä¸ªç³»ç»è°ç¨è¡¨æ å°å°sys_fork(),sys_vfork(),sys_clone(),åå¨è¿ä¸ä¸ªå½æ°ä¸å»è°ç¨do_fork()å»åå ·ä½çå建è¿ç¨å·¥ä½ã
fork
forkå建ä¸ä¸ªè¿ç¨æ¶ï¼åè¿ç¨åªæ¯å®å ¨å¤å¶ç¶è¿ç¨çèµæºï¼å¤å¶åºæ¥çåè¿ç¨æèªå·±çtask_structç»æåpid,ä½å´å¤å¶ç¶è¿ç¨å ¶å®ææçèµæºãä¾å¦ï¼è¦æ¯ç¶è¿ç¨æå¼äºäºä¸ªæ件ï¼é£ä¹åè¿ç¨ä¹æäºä¸ªæå¼çæ件ï¼èä¸è¿äºæ件çå½å读åæéä¹åå¨ç¸åçå°æ¹ãæ以ï¼è¿ä¸æ¥æåçæ¯å¤å¶ãè¿æ ·å¾å°çåè¿ç¨ç¬ç«äºç¶è¿ç¨ï¼ å ·æè¯å¥½ç并åæ§ï¼ä½æ¯äºè ä¹é´çé讯éè¦éè¿ä¸é¨çé讯æºå¶ï¼å¦ï¼pipeï¼å ±äº«å åçæºå¶ï¼ å¦å¤éè¿forkå建åè¿ç¨ï¼éè¦å°ä¸é¢æè¿°çæ¯ç§èµæºé½å¤å¶ä¸ä¸ªå¯æ¬ãè¿æ ·çæ¥ï¼forkæ¯ä¸ä¸ªå¼éåå大çç³»ç»è°ç¨ï¼è¿äºå¼é并ä¸æ¯ææçæ åµä¸é½æ¯å¿ é¡»çï¼æ¯å¦æè¿ç¨forkåºä¸ä¸ªåè¿ç¨åï¼å ¶åè¿ç¨ä» ä» æ¯ä¸ºäºè°ç¨execæ§è¡å¦ä¸ä¸ªå¯æ§è¡æ件ï¼é£ä¹å¨forkè¿ç¨ä¸å¯¹äºèå空é´çå¤å¶å°æ¯ä¸ä¸ªå¤ä½çè¿ç¨ãä½ç±äºç°å¨Linuxä¸æ¯éåäºcopy-on-write(COWåæ¶å¤å¶)ææ¯ï¼ä¸ºäºéä½å¼éï¼forkæå并ä¸ä¼çç产ç两个ä¸åçæ·è´ï¼å 为å¨é£ä¸ªæ¶åï¼å¤§éçæ°æ®å ¶å®å®å ¨æ¯ä¸æ ·çãåæ¶å¤å¶æ¯å¨æ¨è¿çæ£çæ°æ®æ·è´ãè¥åæ¥ç¡®å®åçäºåå ¥ï¼é£æå³çparentåchildçæ°æ®ä¸ä¸è´äºï¼äºæ¯äº§çå¤å¶å¨ä½ï¼æ¯ä¸ªè¿ç¨æ¿å°å±äºèªå·±çé£ä¸ä»½ï¼è¿æ ·å°±å¯ä»¥éä½ç³»ç»è°ç¨çå¼éãæ以æäºåæ¶å¤å¶åå¢ï¼vforkå ¶å®ç°æä¹å°±ä¸å¤§äºã
fork()è°ç¨æ§è¡ä¸æ¬¡è¿å两个å¼ï¼å¯¹äºç¶è¿ç¨ï¼forkå½æ°è¿ååç¨åºçè¿ç¨å·ï¼è对äºåç¨åºï¼forkå½æ°åè¿åé¶ï¼è¿å°±æ¯ä¸ä¸ªå½æ°è¿å两次çæ¬è´¨ã
å¨forkä¹åï¼åè¿ç¨åç¶è¿ç¨é½ä¼ç»§ç»æ§è¡forkè°ç¨ä¹åçæ令ãåè¿ç¨æ¯ç¶è¿ç¨çå¯æ¬ãå®å°è·å¾ç¶è¿ç¨çæ°æ®ç©ºé´ï¼å åæ çå¯æ¬ï¼è¿äºé½æ¯å¯æ¬ï¼ç¶åè¿ç¨å¹¶ä¸å ±äº«è¿é¨åçå åãä¹å°±æ¯è¯´ï¼åè¿ç¨å¯¹ç¶è¿ç¨ä¸çåååéè¿è¡ä¿®æ¹å¹¶ä¸ä¼å½±åå ¶å¨ç¶è¿ç¨ä¸çå¼ãä½æ¯ç¶åè¿ç¨åå ±äº«ä¸äºä¸è¥¿ï¼ç®å说æ¥å°±æ¯ç¨åºçæ£æ段ãæ£æ段åæ¾çç±cpuæ§è¡çæºå¨æ令ï¼é常æ¯read-onlyçã
vfork
vforkç³»ç»è°ç¨ä¸åäºforkï¼ç¨vforkå建çåè¿ç¨ä¸ç¶è¿ç¨å ±äº«å°å空é´ï¼ä¹å°±æ¯è¯´åè¿ç¨å®å ¨è¿è¡å¨ç¶è¿ç¨çå°å空é´ä¸ï¼å¦æè¿æ¶åè¿ç¨ä¿®æ¹äºæ个åéï¼è¿å°å½±åå°ç¶è¿ç¨ã
å æ¤ï¼ä¸é¢çä¾åå¦ææ¹ç¨vfork()çè¯ï¼é£ä¹ä¸¤æ¬¡æå°a,bçå¼æ¯ç¸åçï¼æå¨å°åä¹æ¯ç¸åçã
ä½æ¤å¤æä¸ç¹è¦æ³¨æçæ¯ç¨vfork()å建çåè¿ç¨å¿ é¡»æ¾ç¤ºè°ç¨exit()æ¥ç»æï¼å¦ååè¿ç¨å°ä¸è½ç»æï¼èfork()åä¸åå¨è¿ä¸ªæ åµã
Vforkä¹æ¯å¨ç¶è¿ç¨ä¸è¿ååè¿ç¨çè¿ç¨å·ï¼å¨åè¿ç¨ä¸è¿å0ã
ç¨ vforkå建åè¿ç¨åï¼ç¶è¿ç¨ä¼è¢«é»å¡ç´å°åè¿ç¨è°ç¨exec(execï¼å°ä¸ä¸ªæ°çå¯æ§è¡æä»¶è½½å ¥å°å°å空é´å¹¶æ§è¡ä¹ã)æexitãvforkç好å¤æ¯å¨åè¿ç¨è¢«å建åå¾å¾ä» ä» æ¯ä¸ºäºè°ç¨execæ§è¡å¦ä¸ä¸ªç¨åºï¼å 为å®å°±ä¸ä¼å¯¹ç¶è¿ç¨çå°å空é´æä»»ä½å¼ç¨ï¼æ以对å°å空é´çå¤å¶æ¯å¤ä½ç ï¼å æ¤éè¿vforkå ±äº«å åå¯ä»¥åå°ä¸å¿ è¦çå¼éã
clone
ç³»ç»è°ç¨fork()åvfork()æ¯æ åæ°çï¼èclone()å带æåæ°ãfork()æ¯å ¨é¨å¤å¶ï¼vfork()æ¯å ±äº«å åï¼èclone()æ¯åå¯ä»¥å°ç¶è¿ç¨èµæºæéæ©å°å¤å¶ç»åè¿ç¨ï¼è没æå¤å¶çæ°æ®ç»æåéè¿æéçå¤å¶è®©åè¿ç¨å ±äº«ï¼å ·ä½è¦å¤å¶åªäºèµæºç»åè¿ç¨ï¼ç±åæ°å表ä¸çclone_flagsæ¥å³å®ãå¦å¤ï¼clone()è¿åçæ¯åè¿ç¨çpidã