用户态协议栈三部曲uio、数据框、协议栈100行代码完成用户态协议栈手写一个用户态网络协议栈,瞬间提升你的网络技能LinuxC++后台服务器开发架构师免费学习地址forkfork函数创建子进程成功后,父进程返回子进程的pid,子进程返回0。具体说明如下:fork的返回值为-1,表示子进程创建失败。fork返回值为0,表示子进程创建成功。这个分支就是子进程的运行逻辑。fork返回值大于0,这个分支就是父进程的运行逻辑。,返回值等于子进程的pid我们来看一个通过fork系统调用创建子进程的例子:#include#include#includeintmain(){pid_tpid=fork();if(pid==-1){printf("创建子进程失败!\n");返回-1;}elseif(pid==0){printf("这是子进程!\n");}else{printf("这是父进程!\n");printf("父进程pid=%d\n",getpid());printf("子进程pid=%d\n",pid);}getchar();return0;}运行结果:$./a.out这是父进程!父进程pid=25483子进程pid=25484这是子进程!从上面的运行结果来看,子进程的pid=25484,父进程的pid=25483。在介绍内存页面错误异常时,提到了写时复制(COW)是一种延迟或避免复制数据的技术。主要用于fork系统调用。执行fork创建新的子进程时,内核不需要复制父进程的整个进程地址空间给子进程,而是父进程和子进程共享同一份。只有在写的时候,数据才会被复制。让我们用一个简单的例子来描述它:#include#include#includeintpeter=10;intmain(){pid_tpid=fork();if(pid==-1){printf("创建子进程失败!\n");返回-1;}elseif(pid==0){printf("这是子进程,peter=%d!\n",peter);彼得=100;printf("子进程修改peter=%d\n",peter);}else{printf("这是父进程=%d!\n",peter);}getchar();return0;}执行结果:$./a.outThisisparentprocess=10!Thisischildprocess,peter=10!子进程修改peter=100后从运行结果可以看出,不管子进程如何修改peter的值,父进程总会看到自己的share。vfork接下来看使用vfork创建子进程:#include#include#include#includeintpeter=10;intmain(){pid_tpid=vfork();if(pid==-1){printf("创建子进程失败!\n");返回-1;}elseif(pid==0){printf("这是子进程,peter=%d!\n",peter);彼得=100;printf("子进程修改peter=%d\n",peter);退出(0);}else{printf("这是父进程=%d!\n",peter);}getchar();return0;}运行结果:$./a.outThisischildprocess,peter=10!子进程修改后peter=100Thisisparentprocess=100!从运行结果可以看出,当子进程修改peter=100时,父进程打印的peter的值也是100。【文章受益】:小编整理了一些我个人的学习书籍和视频资料认为更好并在组文件中共享它们。如果需要,可以自己添加!~点击加入(需自行收藏)pthread_create现在我们知道创建进程有两种方式:fork,vfork。创建线程呢?线程创建接口为pthread_create:#include#include#include#include#includeintpeter=10;staticpid_tgettid(void){returnsyscall(SYS_gettid);}staticvoid*thread_call(void*arg){peter=100;printf("创建线程成功!\n");printf("thread_callpid=%d,tid=%d,peter=%d\n",getpid(),gettid(),peter);返回NULL;}intmain(){intret;pthread_t线程;ret=pthread_create(&thread,NULL,thread_call,NULL);if(ret==-1)printf("创建线程失败!\n");ret=pthread_join(thread,NULL);if(ret==-1)printf("pthreadjoinfailed!\n");printf("进程pid=%d,tid=%d,peter=%d\n",getpid(),gettid(),peter);returnret;}运行结果:$./a.outcreatethreadsuccess!thread_callpid=9719,tid=9720,peter=100processpid=9719,tid=9719,peter=100从上面的结果可以看出进程和线程的pid是一样的。当线程修改peter=100时,父进程中打印的peter的值也是100。上面的进程线程创建总图介绍了用户态创建进程和线程的方法,以及每种方法的特点。关于其底层实现的性质,我们将在后面详细说明。这里先给出三者的关系。可见三者最终都会调用do_fork来实现。但是内核态没有进程线程的概念。内核只承认task_struct结构,只要是task_struct结构就可以参与调度。