linux第1天 fork exec 守护进程
概念方面
文件是对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 守护进程的更多相关文章
- Linux学习笔记(9)-守护进程
明天学这个!! ---------------------------------------------------------- 守护进程(Daemon)是运行在后台的一种特殊进程.它独立于控制终 ...
- Linux系统编程(26)——守护进程
Linux系统启动时会启动很多系统服务进程,比如inetd,这些系统服务进程没有控制终端,不能直接和用户交互.其它进程都是在用户登录或运行程序时创建,在运行结束或用户注销时终止,但系统服务进程不受用户 ...
- linux c语言学习笔记之守护进程
哈尔滨理工大学软件工程专业08-7李万鹏原创作品,转载请标明出处 http://blog.csdn.net/woshixingaaa/archive/2010/06/06/5651095.aspx 守 ...
- Java实现Linux下服务器程序的双守护进程
作者:Vinkn 来自http://www.cnblogs.com/Vinkn/ 一.简介 现在的服务器端程序很多都是基于Java开发,针对于Java开发的Socket程序,这样的服务器端上线后出现问 ...
- 基于Linux环境,创建PHP后台守护进程(转载)
应用场景:某些情况下,我们需要持续的周期性的提供一些服务,比如监控内存或cpu的运行状况,这些应用与客户端是没有关系的,不是说客户端(如web界面,手机app等)关闭了,我们就不监控内存或cpu了,为 ...
- Linux+Nginx+Asp.net Core及守护进程部署
上篇<Docker基础入门及示例>文章介绍了Docker部署,以及相关.net core 的打包示例.这篇文章我将以oss.offical.site站点为例,主要介绍下在linux机器下完 ...
- 浅析linux 下shell命令执行和守护进程
执行shell脚本有以下几种方式 1.相对路径方式,需先cd到脚本路径下 [root@banking tmp]# cd /tmp [root@banking tmp]# ./ceshi.sh 脚本执行 ...
- Linux系统添加应用服务进程的守护进程
以前曾在Linux上维护应用服务,但是只是简单的迭代版本等工作,没有什么技术含量.最近部署在Linux服务器上的一个平台的总线进程broker(下面总线用broker指代)经常挂掉,由于总线负责服务之 ...
- 对linux中source,fork,exec的理解以及case的 使用
fork 使用 fork 方式运行 script 时, 就是让 shell(parent process) 产生一个 child process 去执行该 script, 当 child proc ...
随机推荐
- ie6 css sprites重复加载问题
_html{zoom:expression(function(ele){ele.style.zoom = "1";document.execCommand("Backgr ...
- [Virtualization][SDN] VXLAN到底是什么 [转]
写在转发之前: 几个月以前,在北大机房和燕园大厦直接拉了一根光钎.两端彼此为校园内公网IP.为了方便连接彼此机房,我做个一个VPN server在燕园的边界,北大机房使用client拨回.两个物理机房 ...
- LogNet4学习笔记
LogNet是一套开源的程序日志记录系统,经过配置后可以自动抓取程序中的错误.异常信息,并写入磁盘,也可以在异常发生时执行其他指定的操作,比如:通知某人右键.写入数据库等. 这里写个AspNet应用L ...
- 在使用EFCodeFirst中出现类型“System.Data.Objects.ObjectContext”在未被引用的程序集中定义的解决方案
我安装了EF4.1版本,并在一个项目中映射一个数据库并生成了EF的MODEL实体层 测试:在Default.aspx页面上加了个GridView控件,后台进行绑定 using System; usin ...
- python中的类,对象,方法,属性等介绍
注:这篇文章写得很好.加底纹的是我自己的理解 python中一切皆为对象,所谓对象:我自己就是一个对象,我玩的电脑就是对象,坐着的椅子就是对象,家里养的小狗也是一个对象...... 我们通过描述属性( ...
- php--linux环境下的主从复制
1.编辑数据库配置文件my.cnf,一般在/etc/目录下. #vi /etc/my.cnf 在[mysqld]的下面加入下面代码:[第一步查看本文件夹中代码是否已经存在,存在不需要进行添加] 只是修 ...
- 借用layer让弹层不限制在iframe内部
使用方法: 1 除了layer的success,end,cancel回掉函数以外其它的layer参数都可以使用. 2 使用前在layer的js后边把该js引入(可以命名为layerExtend). 3 ...
- JS实现页面回到顶部效果
[代码] <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF- ...
- 查询数据表,去除符合某些条件的记录,没有自动增长列(not exists)
select distinct ccode,isnull(cexch_name,''),N'',N'',N'2014.03',0,1,1,1,12 from RP_bankrecp where not ...
- golang AES/ECB/PKCS5 加密解密 url-safe-base64
因为项目的需要用到golang的一种特殊的加密解密算法AES/ECB/PKCS5,但是算法并没有包含在标准库中,经过多次失败的尝试,终于解码成功,特此分享: /* 描述 : golang AES/EC ...