加载独立进程

注意:当使用 fork
函数加载独立进程的时候,你必须总是在 fork 后面调用
exec 或者类似的函数。

基于 Core Foundation、Cocao
或者 Core Data
框架(无论显式还是隐式关联)的应用程序随后

调用 exec 函数或者类似的函数都会导出不确定的结果。

分叉函数编辑


头文件





1

2

#include<unistd.h>/*#包含<unistd.h>*/

#include<sys/types.h>/*#包含<sys/types.h>*/

函数原型

pid_t forkvoid);

(pid_t 是一个宏定义,其实质是int
被定义在#include<sys/types.h>中)

返回值: 若成功调用一次则返回两个值,子进程返回0,父进程返回子进程ID;否则,出错返回-1

函数说明

一个现有进程可以调用fork函数创建一个新进程。由fork创建的新进程被称为子进程(child
process)。fork函数被调用一次但返回两次。两次返回的唯一区别是子进程中返回0值而父进程中返回子进程ID。

子进程是父进程的副本,它将获得父进程数据空间、堆、栈等资源的副本。注意,子进程持有的是上述存储空间的“副本”,这意味着父子进程间不共享这些存储空间。

UNIX将复制父进程地址空间内容给子进程,因此,子进程有了独立的地址空间。在不同的UNIX
(Like)系统下,我们无法确定fork之后是子进程先运行还是父进程先运行,这依赖于系统的实现。所以在移植代码的时候我们不应该对此作出任何的假设。

为什么fork会返回两次?

由于在复制时复制了父进程堆栈段,所以两个进程都停留在fork函数中,等待返回。因此fork函数会返回两次,一次是在父进程中返回,另一次是在子进程中返回,这两次的返回值是不一样的。过程如下图。

  1. fork调用的一个奇妙之处就是它仅仅被调用一次,却能够返回两次,它可能有三种不同的返回值:
      在父进程中,fork返回新创建子进程的进程ID;

  2. 在子进程中,fork返回0;

  3. 如果出现错误,fork返回一个负值。

在fork函数执行完毕后,如果创建新进程成功,则出现两个进程,一个是子进程,一个是父进程。在子进程中,fork函数返回0,在父进程中,fork返回新创建子进程的进程ID。我们可以通过fork返回的值来判断当前进程是子进程还是父进程。

引用一位网友的话来解释fork函数返回的值为什么在父子进程中不同。“其实就相当于链表,进程形成了链表,父进程的fork函数返回的值指向子进程的进程id,
因为子进程没有子进程,所以其fork函数返回的值为0.

调用fork之后,数据、堆栈有两份,代码仍然为一份但是这个代码段成为两个进程的共享代码段都从fork函数中返回,箭头表示各自的执行处。当父子进程有一个想要修改数据或者堆栈时,两个进程真正分裂。

示例代码:





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

#include<sys/types.h>//对于此程序而言此头文件types.h用不到

#include<unistd.h>

#include<stdio.h>

#include<stdlib.h>

intmain(intargc,char**argv)/*整数类型主函数*/

{

pid_tpid=fork();/*传递参数*/

if(pid<0)/*如果(进程标记<0)*/

{

fprintf(stderr,"错误!");

}

elseif(pid==0)/*否则如果(进程标记==0)*/

{

printf("百度百科:这是子进程!");

_exit(0);

}

else/*否则*/{

printf("百度百科:这是父进程!子进程的进程标记为=%d",pid);

}

//可能需要时候wait或waitpid函数等待子进程的结束并获取结束状态

exit(0);

}

注意!样例代码仅供参考,样例代码存在着父进程在子进程结束前结束的可能性。必要的时候可以使用wait或
waitpid函数让父进程等待子进程的结束并获取子进程的返回状态。

fork()在Linux系统中的返回值是没有NULL的.

Error Codes

出错返回错误信息如下:

EAGAIN

达到进程数上限.

ENOMEM

没有足够空间给一个新进程分配.

fork函数的特点概括起来就是“调用一次,返回两次”,在父进程中调用一次,在父进程和子进程中各返回一次。

fork的另一个特性是所有由父进程打开的描述符都被复制到子进程中。父、子进程中相同编号的文件描述符内核中指向同一个file结构体,也就是说,file结构体的引用计数要增加。

加载独立进程

时间: 2024-10-10 07:09:54

加载独立进程的相关文章

Linux进程创建、可执行文件的加载和进程执行进程切换

作者:刘磊 文中参考代码出处:https://github.com/mengning/linuxkernel/ 本文主要针对进程创建.可执行文件的加载和进程间切换三大部分进行实验并分析. 实验环境:Ubuntu 16虚拟机.VMware 14 1 进程创建 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础.在早期面向进程设计的计算机结构中,进程是程序的基本执行实体:在当代面向线程设计的计算机结构中,进程是线程的容器.程

从整理上理解进程创建、可执行文件的加载和进程执行进程切换,重点理解分析fork、execve和进程切换

一.首先我们来看看进程控制块PCB也就是task_struct,(源码) 选出task_struct中几个关键的参数进行分析 struct task_struct {volatile long state; //进程状态 /* -1 unrunnable, 0 runnable, >0 stopped */ void *stack; //进程内核堆栈 atomic_t usage; unsigned int flags; //进程标识符 /* per process flags, defined

通过进程2加载shell进程,详解execve

一直以来都对execve到底做了什么,总是犯迷糊,原来看Linux内核设计的艺术,这部分讲解的非常不细致,这次结合赵博士的书,重新理解了这部分代码. 首先列出代码,如下: if (!(pid=fork())) {//进程1创建进程2 close(0); if (open("/etc/rc",O_RDONLY,0)) _exit(1); execve("/bin/sh",argv_rc,envp_rc); _exit(2); } 进程1创建进程2,进程2的页目录表及页

ArcGIS API for JavaScript 加载独立GeoWebCache发布的Wmts服务

其实ArcGIS API for JavaScript 也已经有两个例子了,不过就是在一些参数方面,没有解释清楚.Arcgis的例子是以Geoserver发布的服务作为举例的,而这里是用独立的GeoWebCache服务WMTS服务的,地址是http://localhost:8080/geowebcache/service/wmts,按照ArcGIS给出的例子调了两天也没调出来,例子如下(这已经是我改过的): <script> var map, wmtsLayer; require([ &quo

C#卸载加载到进程里的dll

参考 DLL卸载 VC实现DLL注入之DLL卸载 CreateToolhelp32Snapshot (kernel32) CreateToolhelp32Snapshot函数 原文地址:https://www.cnblogs.com/code1992/p/11663090.html

Linux进程启动过程分析do_execve(可执行程序的加载和运行)

日期 内核版本 架构 作者 GitHub CSDN 2016-06-06 Linux-4.5 X86 & arm gatieme LinuxDeviceDrivers Linux进程管理与调度-之-进程的描述 execve系统调用 execve系统调用 我们前面提到了, fork, vfork等复制出来的进程是父进程的一个副本, 那么如何我们想加载新的程序, 可以通过execve来加载和启动新的程序. x86架构下, 其实还实现了一个新的exec的系统调用叫做execveat(自linux-3.

Linux进程启动过程分析do_execve(可执行程序的加载和运行)---Linux进程的管理与调度(十一)

execve系统调用 execve系统调用 我们前面提到了, fork, vfork等复制出来的进程是父进程的一个副本, 那么如何我们想加载新的程序, 可以通过execve来加载和启动新的程序. x86架构下, 其实还实现了一个新的exec的系统调用叫做execveat(自linux-3.19后进入内核) syscalls,x86: Add execveat() system call exec()函数族 exec函数一共有六个,其中execve为内核级系统调用,其他(execl,execle,

Windows API 编程-----DLL编程之禁止加载自己

和可执行文件一样,动态链接库也有自己的入口地址,如果系统或者当前进程的某个线程调用LoadLibrary函数加载或者使用FreeLibrary卸载该动态链接库的时候,会自动使用3个特定的堆栈参数跳转到该地址来运行.入口函数是为了完成动态链接库代码的初始化和善后工作,比如卸载后的资源释放. 这三个参数具有特殊的含义. BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) 第一个参数

CLR是如何被加载并工作的

当运行Windows应用程序的时候,CLR总是默默地为服务着.CLR到底是如何被加载并运行呢? 首先,Microsoft专门为CLR定义了一个标准的COM接口. 安装某个版本的.NET Framework,CLR被包含在DLL中,作为COM服务器在Windows注册表中注册. 一台电脑上可能安装多个版本的CLR.打开开发人员命令提示,输入CLRVer.exe,可以看到当前电脑上安装的CLR版本. 比如,在C:\Windows\Microsoft.NET\Framework\v2.0.50727文