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 ...
随机推荐
- socketlog
说明 SocketLog适合Ajax调试和API调试, 举一个常见的场景,用SocketLog来做微信调试, 我们在做微信API开发的时候,如果API有bug,微信只提示“改公众账号暂时无法提供服务, ...
- JVM内存状况查看方法和分析工具-jmap
jmap -heap 27657 Attaching to process ID 27657, please wait... Debugger attached successfully. Serve ...
- Fedora 11中用MinGW编译Windows的Qt4程序(在Linux系统下编译Windows的程序)
Ubuntu下可以直接安装: sudo apt-get install mingw32 mingw32-binutils mingw32-runtime 安装后编译程序可以: i586-mingw32 ...
- 【Java 基础篇】【第五课】类的构造函数
Java 也有自己的构造函数,如同c++一样有两个特征: 1.构造函数的名字和类的名字相同 2.构造函数没有返回值 下面来看一下这个例子: public class test { public sta ...
- 软件的NABCD----安装部分
N:需求 有些软件安装需要很多的插件,很很多的安装步骤,甚至文件夹移动等麻烦的步骤 A:做法 做成一键安装的程序 B:好处 默认D盘安装,节省C盘空间,没有赘余插件,一键安装,省时省力. C:竞争 和 ...
- svnChina的使用方法
粘贴svn里面项目的地址到Versions里面,这时候,就会显示里面文件夹,将鼠标点击在文件夹上,点击checkout,选择本地要存储的位置,项目就会导出在本地的文件夹.
- Selenium2学习-022-WebUI自动化实战实例-020-JavaScript 在 Selenium 自动化中的应用实例之二(获取浏览器显示区域大小)
前几篇文章中简略概述了,如何获取.设置浏览器窗口大小,那么我们该如何获取浏览器显示区域的大小呢?此文讲对此进行简略概述,敬请各位小主参阅.若有不足之处,敬请各位大神指正,不胜感激! 获取浏览器显示区域 ...
- LeetCode Game of Life
原题链接在这里:https://leetcode.com/problems/game-of-life/ 题目: According to the Wikipedia's article: " ...
- sdut2169:Sequence(dp)
题目:http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2169 #include <iost ...
- Android HttpClient基本使用方法
GET 方式 //先将参数放入List,再对参数进行URL编码 List<BasicNameValuePair> params = new LinkedList<BasicNameV ...