(声明:本篇博客只是博主自己的理解,加以整理,目的是总结刚学过的进程知识,不一定绝对正确,非常愿意听客官您提出宝贵意见。)

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 进程控制 课后习题的更多相关文章

  1. linux&c 进程控制 课后习题

    (声明:本篇博客只是博主自己的理解,加以整理,目的是总结刚学过的进程知识,不一定绝对正确,非常愿意听客官您提出宝贵意见.) Q1:进程中的全局数据段(全局变量),局部数据段(局部变量),静态数据段的分 ...

  2. Linux&C 线程控制 课后习题

    Q1:多线程与多进程相比有什么优势? 多进程程序耗费的资源大,因为fork()的时候子进程需要继承父进程的几乎所有东西,但是多线程程序线程只继承一部分,即自己的私有数据,例如自己的线程ID,一组寄存器 ...

  3. Linux&C 线程控制 课后习题

    Q1:多线程与多进程相比有什么优势? 多进程程序耗费的资源大,因为fork()的时候子进程需要继承父进程的几乎所有东西,但是多线程程序线程只继承一部分,即自己的私有数据,例如自己的线程ID,一组寄存器 ...

  4. linux中进程控制

    1.进程标识 每个进程都有一个非负整型表示的唯一的进程ID.进程ID标识符总是唯一的.  虽然进程ID是唯一的,但某个ID被回收后,ID号是可以复用的. ID为0的进程通常是调度进程(其常常被称交换进 ...

  5. Linux/UNIX进程控制(1)

    进程控制(1) 进程标识符 每一个进程都有肺腑的整形表示唯一的进程ID.按一个进程终止后,其进程ID就能够再次使用了.例如以下是几个典型进程的ID及其类型和功能. ID     进程名         ...

  6. Linux C 程序 进程控制(17)

    进程控制 1.进程概述现代操作系统的特点在于程序的并行执行.Linux是一个多用户多任务的操作系统.ps .pstree 查看进程进程除了进程id外还有一些其他标识信息,可以通过相应的函数获得.// ...

  7. 【linux草鞋应用编程系列】_2_ 环境变量和进程控制

    一. 环境变量     应用程序在执行的时候,可能需要获取系统的环境变量,从而执行一些相应的操作.     在linux中有两种方法获取环境变量,分述如下.   1.通过main函数的参数获取环境变量 ...

  8. 【Linux程序设计】之进程控制&守护进程

    这个系列的博客贴的都是我大二的时候学习Linux系统高级编程时的一些实验程序,都挺简单的. 实验题目:Linux环境下的进程控制 实验目的:熟悉并掌握Linux环境下进程的相关函数的应用:守护进程的概 ...

  9. linux进程及进程控制

    Linux进程控制   程序是一组可执行的静态指令集,而进程(process)是一个执行中的程序实例.利用分时技术,在Linux操作系统上同时可以运行多个进程.分时技术的基本原理是把CPU的运行时间划 ...

随机推荐

  1. Linux python 虚拟环境管理

    直接复制的内容: 原著:https://www.cnblogs.com/q767498226/p/11099884.html 报错解决:https://blog.csdn.net/weixin_467 ...

  2. Selenium+Tesseract-OCR智能识别验证码爬取网页数据

    1.项目需求描述 通过订单号获取某系统内订单的详细数据,不需要账号密码的登录验证,但有图片验证码的动态识别,将获取到的数据存到数据库. 2.整体思路 1.通过Selenium技术,无窗口模式打开浏览器 ...

  3. Spring,AOP实现功能级别权限验证

    1. 首先是问题出现的原因 对于一个我的一个个人博客网站,我希望游客可以浏览我的博客,但是评论功能是需要登录才能使用 这就需要对某个功能进行权限验证 对于过滤器,拦截器,AOP的区别日后再讨论,现在是 ...

  4. 通过Python收集MySQL MHA 部署及运行状态信息的功能实现

    一. 背景介绍 当集团的MySQL数据库实例数达到2000+.MHA集群规模数百个时,对MHA的及时.高效管理是DBA必须面对的一个挑战.MHA 集群 节点信息 和 运行状态 是管理的基础.本篇幅主要 ...

  5. uniapp小程序迁移到TS

    uniapp小程序迁移到TS 我一直在做的小程序就是 山科小站 也已经做了两年了,目前是用uniapp构建的,在这期间也重构好几次了,这次在鹅厂实习感觉受益良多,这又得来一次很大的重构,虽然小程序功能 ...

  6. torch.nn.Sequential()详解

    参考:官方文档    源码 官方文档 nn.Sequential A sequential container. Modules will be added to it in the order th ...

  7. javascript-jquery对象的其他处理

    一.对元素进行遍历操作 如果要遍历一个jquery对象,对其中每个匹配元素进行相应处理,那么可以使用each()方法. $("div").each(function(index,e ...

  8. 【UE4 C++】碰撞检测与事件绑定

    概念 碰撞对象通道与预设 默认提供碰撞对象类型,如 WorldStatic.WorldDynamic等.允许用户自定义 默认提供碰撞预设,如 NoCollision.BloackAll.Overlap ...

  9. .net 5.0 ref文件夹的作用

    ref目录里的dll是一个名为参考组件的东西,微软MSDN给的解释是 参考组件是一种特殊类型的程序集,仅包含表示库的公共API面所需的最小元数据数量.它们包括用于在构建工具中引用程序集时重要的所有成员 ...

  10. 【二食堂】Beta - 测试报告

    Beta - 测试报告 测试过程中发现的bug Beta阶段的新bug 我们在Beta阶段的开发过程中就进行了测试,发现了许多bug.这其中后端的bug比较多,在这里我列举一些比较重要的功能性bug. ...