fork

fork和exec函数

こ雲淡風輕ζ 提交于 2020-03-05 09:29:44
#include<unistd.h> pid_t fork(void); 返回:在子进程中为0,在父进程中为子进程IO,若出错则为-1 fork最困难之处在于调用它一次,它却返回两次。它在调用进程(称为父进程)中返回一次,返回值是新派生进程(称为子进程)的进程ID号;在子进程中又返回一次,返回值为0.因此,返回值本身告知当前进程是子进程还是父进程。 fork在子进程返回0而不是父进程的进程ID的原因在于:任何子进程只有一个父进程,而子进程总是可以通过getppid取得父进程的进程ID。相反,父进程可以有许多子进程而且无法获取各个子进程的进程ID。如果父进程想要跟踪所有子进程的进程ID,那么它必须记录每次调用fork的返回值。 父进程中调用fork之前打开的所有描述符在fork返回之后由子进程分享 。我们将看到网络服务器利用了这个特性:父进程调用accept之后调用fork。所接受的已连接套接字随后就在进程与子进程之间共享。通常情况下,子进程接着读写这个已连接套接字,父进程则关闭这个已连接套接字。 fork的两个典型用法。 (1)一个进程创建一个自身的副本,这样每个副本都可以在另一个副本执行其他任务的同时处理各自的某个操作。这是网络服务器的典型用法。 (2)一个进程想要执行另一个程序。既然创建新进程的唯一方法是调用fork,该进程于是首先调用fork创建一个自身的副本

深入理解Redis的持久化

▼魔方 西西 提交于 2020-03-04 19:57:41
深入理解Redis的持久化 另参考 https://www.jianshu.com/p/9f4a3915df71 RDB RDB是将当前数据生成快照保存到硬盘上。 RDB的工作流程: 执行bgsave命令,Redis父进程判断当前是否存在正在执行的子进程,如RDB/AOF子进程,如果存在bgsave命令直接返回。 父进程执行fork操作创建子进程,fork操作过程中父进程被阻塞。 父进程fork完成后,bgsave命令返回“* Background saving started by pid xxx”信息,并不再阻塞父进程,可以继续响应其他命令。 父进程创建RDB文件,根据父进程内存生成临时快照文件,完成后对原有文件进行原子替换。根据lastsave命令可以获取最近一次生成RDB的时间,对应info Persistence中的rdb_last_save_time。 进程发送信号给父进程表示完胜,父进程更新统计信息。 对于大多数操作系统来说,fork都是个重量级操作,虽然创建的子进程不需要拷贝父进程的物理内存空间,但是会复制父进程的空间内存页表。 子进程通过fork操作产生,占用内存大小等同于父进程,理论上需要两倍的内存来完成持久化操作,但Linux有写时复制机制(copy-on-write)。父子进程会共享相同的物理内存页,当父进程处理写请求时会把要修改的页创建副本

linux fork函数执行过程。

假如想象 提交于 2020-03-02 06:40:51
这两天在看linux的fork函数,把这两天看到的消化一下,说说我的理解。 主要得益与两篇大牛的文章: 推荐先看这篇: 从一道面试题谈linux下的fork运行机制 再看这篇: Linux中fork()函数详解 第一篇虽然只有一个例子,但是感觉把fork的执行过程介绍很详尽,第二篇的例子很经典,但是对刚学的小白来说有点困难。 接下来谈谈看过之后我的总结与理解 首先必须明确一下几点: 1.进程在linux中成树状结构, init为根节点,其它进程均有父进程,某进程的父进程就是启动这个进程的进程,这个进程叫做父进程的子进程。 2.fork函数的作用就是创建一个子进程,子进程复制父进程的代码段,数据段,BSS段,堆,栈等所有用户空间的信息,在内核中操作系统为其重新申请了一个PCB,并且使用父进程的PCB来初始化,除了PID等特殊信息外,几乎所有的信息都是一样的 3.父子进程在创建了子进程后互相不关联,以独立身份抢占CPU资源,具体谁先执行有调度算法决定,用户空间没有办法干预, 4.子进程开始执行代码的位置是fork函数执行后的代码处,之前的都是继承父进程的 下面结合两个例子阐述一下fork的执行 例1: #include <stdio.h> #include <unistd.h> int main(){ int count = 0; pid_t = fork(); if(pid < 0)

多线程程序里不准使用fork

我是研究僧i 提交于 2020-03-02 05:56:37
多线程程序里不准使用fork 一般的,fork做如下事情 父进程的内存数据会原封不动的拷贝到子进程中 子进程在单线程状态下被生成 在内存区域里,静态变量 mutex 的内存会被拷贝到子进程里。而且,父进程里即使存在多个线程,但它们也不会被继承到子进程里。fork 的这两个特征就是造成死锁的原因。 #include <stdio.h> #include <unistd.h> #include <time.h> #include <pthread.h> void *doit(void *arg) { static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_lock(&mutex); fprintf(stderr, "lock... pid = %d\n", getpid()); /* 线程持有锁,进入睡眠 */ struct timespec tc = {10, 0}; nanosleep(&tc, 0); fprintf(stderr, "unlock... pid = %d\n", getpid()); pthread_mutex_unlock(&mutex); return NULL; } int main(int argc, char **argv) { pid_t pid; pthread

进程之fork()函数的详细介绍

旧时模样 提交于 2020-03-02 05:15:54
内容介绍 本博文主要探讨fork函数以及execuv的用法。 头文件介绍 下面的是csapp.h头文件,后面的讨论中均只用该头文件来完成程序的编写。 /* $begin csapp.h */ #ifndef __CSAPP_H__ #define __CSAPP_H__ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <ctype.h> #include <setjmp.h> #include <signal.h> #include <sys/time.h> #include <sys/types.h> #include <sys/wait.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/mman.h> #include <errno.h> #include <math.h> #include <pthread.h> #include <semaphore.h> #include <sys/socket.h> #include <netdb.h> #include <netinet/in.h> #include <arpa/inet.h> /* Default file

fork()两次不同返回值的实现

旧城冷巷雨未停 提交于 2020-03-02 04:46:50
对于fork来说,父子进程共享同一段代码空间,所以给人的感觉好像是有两次返回,其实对于调用fork的父进程来说,如果fork出来的子进程没 有得到 调度,那么父进程从fork系统调用返回,同时分析sys_fork知道,fork返回的是子进程的id。再看fork出来的子进程,由 copy_process函数可以看出,子进程的返回地址为ret_from_fork(和父进程在同一个代码点上返回),返回值直接置为0。所以当子进 程得到调度的时候,也从fork返回,返回值为0。 关键注意两点:1.fork返回后,父进程或子进程的执行位置。(首先会将当前进程eax的值做为返回值)2.两次返回的pid存放的位置。(eax中) 进程调用copy_process得到lastpid的值(放入eax中,fork正常返回后,父进程中返回的就是lastpid) 子进程任务状态段tss的eax被设置成0, fork.c 中 p->tss.eax=0;(如果子进程要执行就需要进程切换,当发生切换时,子进程tss中的eax值就调入eax寄存器,子进程执行时首先会将eax的内容做为返回值) 当子进程开始执行时,copy_process返回eax的值。 fork()后,就是两个任务同时进行,父进程用他的tss,子进程用自己的tss,在切换时,各用各的eax中的值. 所以,“一次调用两次返回”是2个不同的进程!

分析system_call中断处理过程

北战南征 提交于 2020-03-02 04:46:37
最初版本的MenuOS只支持version和help命令,显然这并不能满足我们的需求。我们现在来为它添加一个fork命令和fork-asm命令,其作用是测试fork的系统调用。 要增加一个命令也并不难,只需要~/LinuxKernel/linux-3.18.6/menu/test.c里的main函数中添加下面一行,然后添加它的实现(需要定义在main函数前面)就可以了。 MenuConfig("fork","Test system call fork",Fork); 最后一个参数Fork是一个函数指针,也就是我们对它的定义: int Fork(int argc, char *argv[]) { pid_t fpid; int count = 0; fpid = fork(); printf("Now pid = %d\n", fpid); if(fpid < 0) printf("Error in fork!"); else if(fpid == 0){ printf("I am the child process, my process id is: %d\n", getpid()); count++; } else{ printf("I am the parent process, my process id is: %d\n", getpid()); count++; }

Linux下嵌入汇编代码调用API(using fork())

狂风中的少年 提交于 2020-03-02 04:23:32
以下关于fork()的描述来自于: jason314 首先,在Linux环境下,一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。相当于克隆了一个自己。 fork调用的一个奇妙之处就是它仅仅被调用一次,却能够返回两次,它可能有三种不同的返回值: 1)在父进程中,fork返回新创建子进程的进程ID; 2)在子进程中,fork返回0; 3)如果出现错误(如系统资源不足),fork返回一个负值。 在fork函数执行完毕后,如果创建新进程成功,则出现两个进程,一个是子进程,一个是父进程。在子进程中,fork函数返回0,在父进程中,fork返回新创建子进程的进程ID。我们可以通过fork返回的值来判断当前进程是子进程还是父进程。 现在,我们来写一段程序,使用API调用fork: #include <stdio.h> #include <unistd.h> int main() { pid_t fpid; int count = 0; fpid = fork(); printf("Now pid = %d\n", fpid); if(fpid < 0) printf("Error in fork!"); else if(fpid == 0){ printf("I am the

linux中fork后堆、栈、静态全局、文件描述符中哪些是可以共享的?

﹥>﹥吖頭↗ 提交于 2020-03-01 05:39:08
int pid = fork();之后父进程pid返回非0,子进程pid返回0. 对于执行fork之前的一些变量总结如下: 当父进程调用fork()创建子进程之后,下列哪些变量在子进程中修改之后,父进程里也会相应地作出改动? A.全局变量 函数体外变量 B.局部变量 函数体内变量 C.静态变量 static修饰 D.文件指针 文件描述符 E.一般变量指针 堆上动态分配内存 只有D文件指针也就是文件描述符会发生改变,因为文件描述符存在于系统中为所有进程所共享,close也要父子进程都关一次才能最终官关闭。 来源: CSDN 作者: lsxa123 链接: https://blog.csdn.net/lsxa123/article/details/104582025

GCC declarations: typedef __pid_t pid_t?

∥☆過路亽.° 提交于 2020-03-01 02:33:25
问题 I am confused about the declaration of (for example) pid_t. What does __pid_t mean? Is it another type defined elsewhere? If yes, where? Why is my types.h in ubuntu 13.04 64bit defining pid_t like: #ifndef __pid_t_defined typedef __pid_t pid_t; #define __pid_t_defined #endif and not something like typedef int pid_t; I saw some websites that have types.h headers with the declaration done the last way. This is one: http://www.sde.cs.titech.ac.jp/~gondow/dwarf2-xml/HTML-rxref/app/gcc-3.3.2/lib