linux&c 进程控制 课后习题
(声明:本篇博客只是博主自己的理解,加以整理,目的是总结刚学过的进程知识,不一定绝对正确,非常愿意听客官您提出宝贵意见。)
Q1:进程中的全局数据段(全局变量),局部数据段(局部变量),静态数据段的分别位于哪个内存地址空间?
答:对于进程的概念,我把它理解一个可执行程序进行的实体,我们c语言代码在变成可执行文件的过程中都会经历下面4步(以我们大家接触的第一个c语言程序“helloworld”为例)
(1)预处理:将中的内容和一些宏定义展开,将if,else等判断处理,将注释转化为空格等,我们可以执行 gcc -E helloworld.c -o helloworld.i 来获取预处理之后的文件,在hellowrold.i文件末尾,我们可以找到我们短短的几行程序。
(2)编译:编译的过程主要是编译器对我们代码的语法,词法分析,我们编译器的报错机制就是这部分的体现。同样,我们可以执行 gcc -S helloworld.c -o helloworld.s 同样我们可以看到它的汇编指令(编译的结果得到的是汇编指令)。当然我不懂汇编指令。就不多说了。
(3)汇编:汇编的过程是将我们的汇编指令转化为我们的计算机能够识别的机器指令。
(4)链接:生成我们的可执行文件的过程,可执行的概念是可以被加载或者可以被拷贝到存储器中等待执行。
如果我们运行它,它就会成为一个进程,程序到进程大概是这个过程,首先内核将程序读入内存,并且内存为其分配相应的内存空间,然后内核为其分配pid,和其他所需资源,接着内核会保存pid以及相应的状态信息,并且把进程放到运行队列里等待执行,要是被操作系统调度使用,进程就建立。下来我们进入我们要回答的问题:进程的内存映像是指程序在内存中的状态,也可以说在内存中如何存放的。linux系统的内存映像一般是这样,从内存的地址由低到高依次为:代码段,静态数据段(以被初始化的变量,全局变量和静态变量),动态数据段(malloc),堆段,栈段,命令行参数和环境量。
Q2:列举子进程的父进程的异同。
答:fork()函数是我们用户能唯一使用的创建进程的方式,在fork()和vfork()中,子进程和父进程的特点是不同的:
子进程和父进程相同点 子进程和父进程不同点
fork() 子进程继承父进程的下列信息:
1)用户ID,组ID,当前工作目录,根目录,打开的文件
2)创建文件时使用的屏蔽字,信号屏蔽字,上下文环境,等 1)有它自己的pid
2)不同的父进程ID
3)子进程共享父进程打开的文件描述符,但父进程对文件描述符的改变不会影响子进程中的文件描述符。
4)子进程不继承父进程设置的文件锁和警告。
vfork()
与fork()不同 同样子进程会继承这些父进程的信息 除了上面说的之外,补充一点:
vfork()之后并不会将父进程的地址空间完全复制给子进程,子进程会在父进程的地址空间上运行,这一点和线程的概念是相似的
Q3:如何创建一个后台进程(守护进程)?
答:对于守护进程的概念,我自己认为linux下最简单的例子就是服务了,比如我们安装vsftp服务,并且给它设置enable(开机自动启动),当我们的系统启动之后,它就已经正常工作了,只要我们不关机,它就一直在后台运行,它是独立于我的控制终端的;还有我们要把自己的一块磁盘挂载到某个mountpoint上,但是每次自己手动挂载都很麻烦,我们就可以设置开机自动挂载,vim /etc/fstab 文件,再次开机之后,它就已经挂载好了。我们的计算机要是要提供某种服务,就必须会创建守护进程。步骤大概有5步
void create_daemon();
void create_daemon()
{
int pid;
int i;
pid = fork(); 1 //先让父进程fork一个进程
if(pid > 0) //结束父进程,让子进程脱离当前进程独立
exit(0);
setsid(); 2 //设置子进程为会话组组长.
pid = fork(); 3 //再次fork一个子进程,并让父进程退出。
if(pid > 0) 4 //禁止进程重新打开控制终端,现在进程已经成为一个无终端的会话组组长,但是它可以申请来打 开一个终端,,为了避免这种情况,可以通过进程不再是会话组组长实现,所以再次fork;
exit(0);
for(i = 0;i < NOFILE;close(i++)) 5 //关闭继承的父进程的所有打开的文件描述符
;
umask(0); //将文件创建时屏蔽字设置为零(权限设置为777),因为从父进程继承的东西可能屏蔽掉某种权限
chdir("/"); //当守护进程的工作目录在一个装配文件目录中时,它不可卸载,一般需要将根目录设置为工作目录
signal(SIGCHLD,SIG_IGN); //这样可以保证子进程不会产生僵尸进程。
}
int main(int argc,char *argv[])
{
printf("create a daemon\n");
create_daemon();
while(1) //守护进程我们通常让它周期的执行某种任务,所以我们会让它在while(1)循环中执行
{
sleep(1);
}
}
进程组:一个进程组中包含好几个进程或者一个进程,拥有进程组ID,进程组ID就是进程组组长的ID。
会话组:会话组是一个或者几个进程组的集合,通常一个会话组开始于一个用户的登录,结束于用户的退出,
setsid()作用:让进程摆脱原进程组,会话组,以及终端的控制。
Q4:在多进程中,父子进程的运行顺序是怎样的。
答:fork之后的函数,无论多进程还是单进程,父进程与子进程的运行顺序是不确定的,由内核的调度算法来确定。
vfork之后的函数就可以保证子进程先执行。具体代码可以浏览我的这篇博客:http://blog.chinaunix.net/uid-30131847-id-5137459.html
Q5:有一个全局变量 i 的初值为5,父进程对其进行加1操作,子进程看到的 i 的值是多少?
答:对于这个问题,fork()和vfork()得到的结果是不一样的。
int globvar = 6;
int main(int argc,char *argv[])
{
int pid;
int var = 5;
printf("now var is %d ,globvar is %d\n",var,globvar);
// pid = fork();
pid = vfork();
switch(pid)
{
case 0:
var++;
globvar++;
printf("child process var is %d, globvar is %d\n",var,globvar);
exit(0);
default:
var++;
globvar++;
printf("father process var is %d, globvar is %d\n",var,globvar);
exit(0);
}
exit(0);
}
fork的执行结果:
now var is 5 ,globvar is 6 //fork函数子进程继承父进程的全局和局部变量之后,分别执行各自的代码,
father process var is 6, globvar is 7 //所以因为初始变量相同,执行的程序也相同,他们的值也相同
child process var is 6, globvar is 7
vfork的执行结果: //vfork函数保证子进程先执行,由于它在父进程地址上运行,所以它先对两个变量的改变对于
now var is 5 ,globvar is 6 //父进程是可见的,子进程运行完之后,父进程得到已经被改变一次的变量值继续运行。
child process var is 6, globvar is 7
father process var is 7, globvar is 8
fork()函数的一瞬间全局变量和局部变量已经被子进程继承,以后他们运行在不同的地址空间,父进程更改,对于子进程是不可见的。
vfork()函数虽然子进程运行在父进程的地址空间上,但是vfork()保证了子进程的优先运行,应此父进程更改全局变量,子进程看不到。
linux&c 进程控制 课后习题的更多相关文章
- linux&c 进程控制 课后习题
(声明:本篇博客只是博主自己的理解,加以整理,目的是总结刚学过的进程知识,不一定绝对正确,非常愿意听客官您提出宝贵意见.) Q1:进程中的全局数据段(全局变量),局部数据段(局部变量),静态数据段的分 ...
- Linux&C 线程控制 课后习题
Q1:多线程与多进程相比有什么优势? 多进程程序耗费的资源大,因为fork()的时候子进程需要继承父进程的几乎所有东西,但是多线程程序线程只继承一部分,即自己的私有数据,例如自己的线程ID,一组寄存器 ...
- Linux&C 线程控制 课后习题
Q1:多线程与多进程相比有什么优势? 多进程程序耗费的资源大,因为fork()的时候子进程需要继承父进程的几乎所有东西,但是多线程程序线程只继承一部分,即自己的私有数据,例如自己的线程ID,一组寄存器 ...
- linux中进程控制
1.进程标识 每个进程都有一个非负整型表示的唯一的进程ID.进程ID标识符总是唯一的. 虽然进程ID是唯一的,但某个ID被回收后,ID号是可以复用的. ID为0的进程通常是调度进程(其常常被称交换进 ...
- Linux/UNIX进程控制(1)
进程控制(1) 进程标识符 每一个进程都有肺腑的整形表示唯一的进程ID.按一个进程终止后,其进程ID就能够再次使用了.例如以下是几个典型进程的ID及其类型和功能. ID 进程名 ...
- Linux C 程序 进程控制(17)
进程控制 1.进程概述现代操作系统的特点在于程序的并行执行.Linux是一个多用户多任务的操作系统.ps .pstree 查看进程进程除了进程id外还有一些其他标识信息,可以通过相应的函数获得.// ...
- 【linux草鞋应用编程系列】_2_ 环境变量和进程控制
一. 环境变量 应用程序在执行的时候,可能需要获取系统的环境变量,从而执行一些相应的操作. 在linux中有两种方法获取环境变量,分述如下. 1.通过main函数的参数获取环境变量 ...
- 【Linux程序设计】之进程控制&守护进程
这个系列的博客贴的都是我大二的时候学习Linux系统高级编程时的一些实验程序,都挺简单的. 实验题目:Linux环境下的进程控制 实验目的:熟悉并掌握Linux环境下进程的相关函数的应用:守护进程的概 ...
- linux进程及进程控制
Linux进程控制 程序是一组可执行的静态指令集,而进程(process)是一个执行中的程序实例.利用分时技术,在Linux操作系统上同时可以运行多个进程.分时技术的基本原理是把CPU的运行时间划 ...
随机推荐
- Jmeter系列(18)- 八大组件
说明 取样器(Sampler):不与其他元件发⽣交互的作⽤的元件 逻辑控制器(Logic Controller):只对其⼦节点的sampler有效,⽽其他元件需要与sampler等元件交互 前置处理器 ...
- php curl 发送post请求
PHP curl_init函数 resource curl_init ([ string $url = NULL ] ) 初始化一个新的会话,返回一个cURL句柄,供curl_setopt(), cu ...
- P4590-[TJOI2018]游园会【dp套dp】
正题 题目链接:https://www.luogu.com.cn/problem/P4590 题目大意 给出一个长度为\(m\)的字符串\(s\). 对于每个\(k\in[0,m]\)求有多少个长度为 ...
- P3335-[ZJOI2013]蚂蚁寻路【dp】
正题 题目链接:https://www.luogu.com.cn/problem/P3335 题目大意 给出\(n\times m\)的网格,每个格子有权值.一个回路在格子的边上,要求有\(2\tim ...
- CF891E-Lust【EGF】
正题 题目链接:https://www.luogu.com.cn/problem/CF891E 题目大意 \(n\)个数字的一个序列\(a_i\),每次随机选择一个让它减去一.然后贡献加上所有其他\( ...
- Css预编译(Sass&&Less)
目录 Less与Sass是css的预处理技术 而CoffeeScript.TypeScript则是javascript的预处理技术. Less与Sass是css的预处理技术 而CoffeeScript ...
- 实验4:开源控制器实践——OpenDaylight
实验4:开源控制器实践--OpenDaylight 一.实验目的 能够独立完成OpenDaylight控制器的安装配置: 能够使用Postman工具调用OpenDaylight API接口下发流表. ...
- Spring MVC面试复习整理
Spring MVC Spring MVC 是Spring Framework 提供的 web 组件 它的实现基于 MVC 的设计模式:Model(模型层).View(视图层).Controller( ...
- python-docx 页面设置
初识word文档-节-的概念 编辑一篇word文档,往往首先从页面设置开始,从下图可以看出,页面设置常操作的有页边距.纸张方向.纸张大小4个,而在word中是以节(section)来分大的块,每一节的 ...
- android-- 按需打包的框架搭建--新手教程
1, 新建项目VariantTest 2, 生成keystore 可以看到, 默认的build variant只有debug一种 当我试图选release的时候,发现报错了 什么错呢 大致意思是说我们 ...