概念方面

文件是对I/O设备的抽象表示、虚拟存储器是对主存和磁盘I/O设备的抽象表示、进程则是对处理器、主存和I/O设备的抽象表示

中断

早期是没有进程这个概念,当出现中断技术以后才出现进程这个概念

分式操作系统

基于时间片轮转

进程是操作系统对资源的一种抽象,一个进程:代码段、数据段、堆栈段、+进程控制块(PCB)

PCB是操作系统感知进程存在的一个重要数据结构(cpu通过进程控制块来控制进程)

fork()

使用fork函数得到的子进程从父进程的继承了整个进程的地址空间,包括:进程上下文、进程堆栈、内存信息、打开的文件描述符、信号控制设置、进程优先级、进程组号、当前工作目录、根目录、资源限制、控制终端等,,进程PCB控制块。

子进程与父进程的区别在于:

1、父进程设置的锁,子进程不继承

2、各自的进程ID和父进程ID不同

3、子进程的未决告警被清除;

4、子进程的未决信号集设置为空集。

理解1:fork系统调用之后,父子进程将交替执行。

理解2:怎么样理解一次调用2次返回? 父子进程将在各自的进程空间里返回.

理解3:怎么样理解,fork返回值大于零的是父进程,为什么这样设计:?通过子进程获取父进程简单getppid(),而通过父进程获取子进程麻烦,还不如把子进程pid设置为0

理解4:怎么样理解分支在fork之后,而不是父进程main函数的开始?子进程继承父进程的.进程上下文、进程堆栈、内存信息、打开的文件描述符、信号控制设置、进程优先级、进程组号、当前工作目录、根目录、资源限制、控制终端等,,进程PCB控制块。

写时复制copy on write

如果多个进程要读取它们自己的那部分资源的副本,那么继承时复制是不必要的。

每个进程只要保存一个指向这个不需要写入数据的资源的指针就可以了。

如果一个进程要修改自己的那份资源的“副本”,那么就会复制那份资源对应的页。这就是写时复制的含义

原因分析:加快速度,linux内核是段页式管理机制(因段管理从0开始,),也可叫页式管理机制。只复制对应的页。缺页,在中断查询,再赋值。

对父进程打开的文件,子进程也会继承过来.然后被打开的文件中,文件表中refcnt引用加1

对于信号方面,子进程继承阻塞信号设置,但要抛弃父进程的未决信号集

fork和vfork

1)在fork还没实现copy on write之前。Unix设计者很关心fork之后立刻执行exec所造成的地址空间浪费,所以引入了vfork系统调用。

2)vfork有个限制,子进程必须立刻执行_exit或者exec函数。

即使fork实现了copy on write,效率也没有vfork高,但是我们不推荐使用vfork,因为几乎每一个vfork的实现,都或多或少存在一定的问题。

结论:

1:fork子进程拷贝父进程的数据段

Vfork子进程与父进程共享数据段;

2:fork父、子进程的执行次序不确定

Vfork:子进程先运行,父进程后运行;

exec函数族

execve替换进程映像(加载程序)注意execve是一个系统调用;

替换意味着:代码段、数据段、堆栈段、进程控制块PCB全部替换。

int main(void)
{
int fd;
pid_t pid;
signal(SIGCHLD, SIG_IGN);//不接收SIGCHILD信号,父进程关闭会子进程直接给1号进程管制
printf("befor fork pid:%d \n", getpid()); g_num = 10; pid = vfork();//不稳定,退出时可能会出现错误.
if (pid == -1)
{
printf("pid < 0 err.\n");
return -1;
} if (pid > 0)
{
printf("parent: pid:%d \n", getpid());
}
else if (pid == 0)
{
printf("child: %d, parent: %d \n", getpid(), getppid()); char *const argv[] = {"ls", "-lt", NULL};
execve("/bin/ls", argv, NULL); //注意:此处有/bin/ls程序结束程序,不会出现coredump现象 printf("测试下面这句话还执行吗\n");
//exit(0);
//1 vfork只有需要用exit(0) _exit(0)
//2 测试return 0; 区别
} printf("fork after....\n");
return 0;
}

  

进程终止的5种方式

正常退出

从main函数返回

调用exit      会清空缓冲区,再调用内核中的退出函数

调用_exit    直接调用内核中的退出函数

异常退出

调用abort   产生SIGABOUT信号 强制关闭

由信号终止  ctrl+c SIGINT      强制关闭

atexit可以注册终止处理程序,ANSI C规定最多可以注册32个终止处理程序,它其实也是一个回调函数,传入的是函数指针

exec关联的函数族

q  包含头文件<unistd.h>

q  功能用exec函数可以把当前进程替换为一个新进程。exec名下是由多个关联函数组成的一个完整系列,头文件<unistd.h>

q  原型

/*

#include <unistd.h>

extern char **environ;

int execl(const char *path, const char *arg, ...);

int execlp(const char *file, const char *arg, ...); PATH

int execle(const char *path, const char *arg,

..., char * const envp[]);

int execv(const char *path, char *const argv[]);

int execvp(const char *file, char *const argv[]);

以execlp、execvp、和execle讲解

path参数表示你要启动程序的名称包括路径名

arg参数表示启动程序所带的参数

返回值:成功返回0,失败返回-1

execl,execlp,execle(都带“l”)的参数个数是可变的,参数以一个空指针结束。

execv和execvp的第二个参数是一个字符串数组,新程序在启动时会把在argv数组中给定的参数传递到main

这些函数通常都是用execve实现的,这是一种约定俗成的做法,并不是非这样不可。

名字最后一个字母是“p”的函数会搜索PATH环境变量去查找新程序的可执行文件。如果可执行文件不在PATH定义的路径上,就必须把包括子目录在内的绝对文件名做为一个参数传递给这些函数

总结:l代表可变参数列表,p代表在path环境变量中搜索file文件。envp代表环境变量。

int main(void)
{
//演示程序被完全替换
//替换以后,pid不会发生变化
//注意 printf后的\n不能忘记,不然main函数打印不出来,
//因为 \n 具有清除缓冲区的作用
printf(“main getpid: %d\n”, getpid()); //execlp(“ls”, “ls”, “-lt”, NULL);
int ret = execlp(“./testpid2”, NULL, NULL);
if (ret == -1)
{
perror(“ERR: “);
} printf(“fork after….\n”);
return 0;
}

  

extern char **environ;//由内核分配内存,内存的第三种模型,

有关环境变量
int main(int argc, char *argv[])
{
printf(“main egin…\n”);
//1)如果envp环境参数列表不填写,则testpidandenv程序会使用默认的环境参数列表
//2)如果envp环境参数列表填写,则testpidandenv程序会使用你填写的环境参数列表
char *ars[] = {“aa=111”, “bb==222”, NULL}; int ret = execle(“./testpidandenv”,”testpidandenv”, NULL,NULL);
//int ret = execle(“./testpidandenv”,”testpidandenv”, NULL,ars); if (ret == -1)
{
perror("main:");
}
printf("main end...\n");
return 0;
}

  

关于守护进程相关知识,顺便加强一下shell知识

当我们用telnet登陆linux服务器,验证好帐号密码之后,会建立一个会话期(session),同时服务器会运行一个shell,针对登陆上的帐户而言

此时,我们在这个终端上运行的所有程序命令都基于这个会话期,一旦终端关闭,运行于这个会话期的所有程序都会关闭,linux内核提供了一个函数setsid

脱离了终端,脱离了这个session,就像WINDOWS的服务程序一样,驻留在linux中,故名思议,守护进程.

注:调用setsid的不能是进程组长(一般为父进程),通常的做法是fork一个子进程,然后再调用setsid,

调用之后,需要改变当前路径为根路径,因为程序启动时,是与启动路径绑定的,如果不改变,将来要对启动路径作某些更改的时候,会失败.

另外还需要将标准输入,输出,错误文件描述符都重定项到"dev/null",避免资源浪费

linux第1天 fork exec 守护进程的更多相关文章

  1. Linux学习笔记(9)-守护进程

    明天学这个!! ---------------------------------------------------------- 守护进程(Daemon)是运行在后台的一种特殊进程.它独立于控制终 ...

  2. Linux系统编程(26)——守护进程

    Linux系统启动时会启动很多系统服务进程,比如inetd,这些系统服务进程没有控制终端,不能直接和用户交互.其它进程都是在用户登录或运行程序时创建,在运行结束或用户注销时终止,但系统服务进程不受用户 ...

  3. linux c语言学习笔记之守护进程

    哈尔滨理工大学软件工程专业08-7李万鹏原创作品,转载请标明出处 http://blog.csdn.net/woshixingaaa/archive/2010/06/06/5651095.aspx 守 ...

  4. Java实现Linux下服务器程序的双守护进程

    作者:Vinkn 来自http://www.cnblogs.com/Vinkn/ 一.简介 现在的服务器端程序很多都是基于Java开发,针对于Java开发的Socket程序,这样的服务器端上线后出现问 ...

  5. 基于Linux环境,创建PHP后台守护进程(转载)

    应用场景:某些情况下,我们需要持续的周期性的提供一些服务,比如监控内存或cpu的运行状况,这些应用与客户端是没有关系的,不是说客户端(如web界面,手机app等)关闭了,我们就不监控内存或cpu了,为 ...

  6. Linux+Nginx+Asp.net Core及守护进程部署

    上篇<Docker基础入门及示例>文章介绍了Docker部署,以及相关.net core 的打包示例.这篇文章我将以oss.offical.site站点为例,主要介绍下在linux机器下完 ...

  7. 浅析linux 下shell命令执行和守护进程

    执行shell脚本有以下几种方式 1.相对路径方式,需先cd到脚本路径下 [root@banking tmp]# cd /tmp [root@banking tmp]# ./ceshi.sh 脚本执行 ...

  8. Linux系统添加应用服务进程的守护进程

    以前曾在Linux上维护应用服务,但是只是简单的迭代版本等工作,没有什么技术含量.最近部署在Linux服务器上的一个平台的总线进程broker(下面总线用broker指代)经常挂掉,由于总线负责服务之 ...

  9. 对linux中source,fork,exec的理解以及case的 使用

    fork   使用 fork 方式运行 script 时, 就是让 shell(parent process) 产生一个 child process 去执行该 script, 当 child proc ...

随机推荐

  1. Bootstrap 表单和图片 (内联表单,表单合组,水平排列,复选框和单选框,下拉列表,校验状态,添加额外的图标,控制尺寸,图片)

    一.表单 基本格式 注:只有正确设置了输入框的 type 类型,才能被赋予正确的样式. 支持的输入框控件 包括:text.password.datetime.datetime-local.date.m ...

  2. USBDongle及Btool使用说明

    BLE 模块可使用开发套件中的 USB Dongle 模拟手机APP配合Btool.exe 进行蓝牙通讯测试. >连接 BLE 模块 USB Dongle 和模块的连接是通讯的基础,扫描连接的操 ...

  3. java JDK8 学习笔记——第17章 反射与类加载器

    第十七章 反射与类加载器 17.1 运用反射 反射:.class文档反映了类基本信息,从Class等API取得类信息的方式称为反射. 17.1.1 Class与.class文档 1.java.lang ...

  4. redis配置文件中文解释

    # redis 配置文件示例 # 当你需要为某个配置项指定内存大小的时候,必须要带上单位, # 通常的格式就是 1k 5gb 4m 等酱紫: # # 1k => bytes # 1kb => ...

  5. isset和empty比较

    PHP的isset()函数 一般用来检测变量是否设置 格式:bool isset ( mixed var [, mixed var [, ...]] ) 功能:检测变量是否设置 返回值: 若变量不存在 ...

  6. sell -- 解码16进制unicode

    1. //System.out.println("decodeUnicode:" + decodeUnicode("0049"));//I public sta ...

  7. Windows 服务器使用FTP出现“当前的安全设置不允许从该位置下载文件" 警告

    为了安全,Windows服务器默认禁用了从网上下载文件的安全选项.此错误即是出现在这里,所以打开这个选项即可: 控制面板  —— Internet选项 ——安全 —— 找到“自定义级别” —— 找到“ ...

  8. LeetCode Binary Tree Upside Down

    原题链接在这里:https://leetcode.com/problems/binary-tree-upside-down/ Given a binary tree where all the rig ...

  9. oracle视图V$BH && X$BH的使用列子

    1创建一个测试表,test,并且插入10000行数据:    SQL>  create table test (id int); SQL> begin      2  for i in 1 ...

  10. Docker镜像的创建、存出、载入

    创建镜像的方法有三种:基于已有镜像的容器创建.基于本地模板导入.基于Dockerfile创建,本博文讲解前两种. 基于已有镜像的容器创建 该方法是使用docker commit命令,其命令格式为:   ...