赞
踩
目录
pid_t fork(void);
pid_t是int类型代表进程的pid号
Linux内核2.4.0定义:
typedef int __kernel_pid_t;
typedef __kernel_pid_t pid_t;
每一个进程的pid都是唯一的,同一个程序每次运行都会产生一个新进程,pid不一样但他们的名字是一样的。
理论上可以产生int表示的上限个进程。每一个进程都有一个PCB(内存控制块,是一个结构体struct task_struct),里面包含pid等信息。
fork函数复制当前进程生成一个新进程,调用fork的为父进程,新生成的为子进程。fork在父子进程中都会有返回值:父进程中返回子进程的pid,子进程创建成功返回0,创建失败返回-1。
所有父进程的资源都拷贝给子进程(父进程定义的东西子进程都有),父子进程一起执行,子进程从fork()返回之后开始执行(所以不会无限执行)。
使用父子进程可以用同一套代码完成不同的事情
下面使用父子进程分别打印两个字符串
输出,父子进程并发执行
pid从1开始往大增长,父进程的pid要比子进程小。
getpid()可以得到自己的pid
getppid()可以得到父进程的pid
父子进程是相对的,子进程再用fork那它就是fork出来进程的父进程了
逻辑地址是指在应用程序角度看到的内存单元、存储单元、网络主机的地址。
物理地址是数据在存储器中的地址。每一个字节单元给以一个唯一的存储器地址。又叫实际地址或绝对地址。
在父进程和子进程中,同一个变量的输出的地址是相同的
但是它们使用的是不同的空间,可以看到它们存放不同的数值,这可以证明它们的物理地址不是相同的,只是逻辑地址相同。程序输出的都是逻辑地址(相对nul偏移量),物理地址是看不到的。
上面代码中n作为临时变量离起始位置偏移量很远:
下面以32位操作系统为例:
每一个进程的逻辑地址都是由存放代码段(函数)、数据段(全局变量)、堆(new/malloc)、栈(临时变量)、内核的空间构成,并依次远离0x0000 0000位置。如下图:
堆往0xffff ffff方向增长,栈往0x0000 0000方向增长。另外代码段初始位置到0x00000000是有一定空间的,这些空间不能被使用代码段的初始地址:0x0804 8000。 4G空间不一定全部用完,代码少的时候代码段大约会使用一页(4k)。
栈(以栈帧为单位)地址从是从0xbfff ffff开始增长,栈内的变量的地址还是从小到大地址使用的,为了保证程序的安全性,栈不是贴着内核开始增长的。
每个进程都有一块逻辑地址的空间,这也是不同程序中输出变量的地址可能相同的原因。
这是64位操作系统的:
十六进制的1000转化成十进制为4096——4k,一个页面大小
malloc时如果没有free,当进程结束时,系统会自动回收空间。如果malloc的少程序运行时间短,不free并不会导致内存泄漏,而且因为有交换空间,我们可以申请比物理内存剩余大一点的内存空间。
32位系统malloc申请空间理论值<3G(考虑当前物理内存剩余空间+虚拟内存剩余空间大小)
Linux的交换空间是一段虚拟内存。虚拟内存不是内存,而是硬盘上的一段空闲空间。
虚拟内存为每个进程提供了一个一致的、私有的地址空间,它让每个进程产生了一种自己在独享主存的错觉(每个进程拥有一片连续完整的内存空间)。
这样会更加有效地管理内存并减少出错。当物理内存不足时,将会使用虚拟内存,但它的访问速度没有内存快。当使用虚拟内存中的东西时,虚拟内存将往物理内存回调。
如果父子进程用的统一变量的值是一样的,则让它们使用同一物理空间,当父或子进程的变量更改了再给它们分不同空间,这样提高fork的效率。
当它们用同一空间时,会有一个变量记录用这个空间的进程数量,如果一个进程结束,引用计数-1,另一个可以继续用,不会将这个空间释放。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。