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



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步

点击(此处)折叠或打开

  1. void create_daemon();
  2. void create_daemon()
  3. {
  4. int pid;
  5. int i;
  6. pid = fork();                                        1 //先让父进程fork一个进程
  7. if(pid > 0)                                            //结束父进程,让子进程脱离当前进程独立
  8. exit(0);
  9. setsid();                                            2 //设置子进程为会话组组长.
  10. pid = fork();                                        3 //再次fork一个子进程,并让父进程退出。
  11. if(pid > 0)                                          4 //禁止进程重新打开控制终端,现在进程已经成为一个无终端的会话组组长,但是它可以申请来打                                                             开一个终端,,为了避免这种情况,可以通过进程不再是会话组组长实现,所以再次fork;
  12. exit(0);
  13. for(i = 0;i < NOFILE;close(i++))                      5 //关闭继承的父进程的所有打开的文件描述符
  14. ;
  15. umask(0);                                             //将文件创建时屏蔽字设置为零(权限设置为777),因为从父进程继承的东西可能屏蔽掉某种权限
  16. chdir("/");                                           //当守护进程的工作目录在一个装配文件目录中时,它不可卸载,一般需要将根目录设置为工作目录
  17. signal(SIGCHLD,SIG_IGN);                               //这样可以保证子进程不会产生僵尸进程。
  18. }
  19. int main(int argc,char *argv[])
  20. {
  21. printf("create a daemon\n");
  22. create_daemon();
  23. while(1)                                                //守护进程我们通常让它周期的执行某种任务,所以我们会让它在while(1)循环中执行
  24. {
  25. sleep(1);
  26. }
  27. }

进程组:一个进程组中包含好几个进程或者一个进程,拥有进程组ID,进程组ID就是进程组组长的ID。

会话组:会话组是一个或者几个进程组的集合,通常一个会话组开始于一个用户的登录,结束于用户的退出,

setsid()作用:让进程摆脱原进程组,会话组,以及终端的控制。

Q4:在多进程中,父子进程的运行顺序是怎样的。

答:fork之后的函数,无论多进程还是单进程,父进程与子进程的运行顺序是不确定的,由内核的调度算法来确定。

     vfork之后的函数就可以保证子进程先执行。具体代码可以浏览我的这篇博客:http://blog.chinaunix.net/uid-30131847-id-5137459.html

Q5:有一个全局变量 i 的初值为5,父进程对其进行加1操作,子进程看到的 i 的值是多少?

答:对于这个问题,fork()和vfork()得到的结果是不一样的。

点击(此处)折叠或打开

  1. int globvar = 6;
  2. int main(int argc,char *argv[])
  3. {
  4. int pid;
  5. int var = 5;
  6. printf("now var is %d ,globvar is %d\n",var,globvar);
  7. // pid = fork();
  8. pid = vfork();
  9. switch(pid)
  10. {
  11. case 0:
  12. var++;
  13. globvar++;
  14. printf("child process var is %d, globvar is %d\n",var,globvar);
  15. exit(0);
  16. default:
  17. var++;
  18. globvar++;
  19. printf("father process var is %d, globvar is %d\n",var,globvar);
  20. exit(0);
  21. }
  22. exit(0);
  23. }
  24. fork的执行结果:
  25. now var is 5 ,globvar is 6                          //fork函数子进程继承父进程的全局和局部变量之后,分别执行各自的代码,
  26. father process var is 6, globvar is 7               //所以因为初始变量相同,执行的程序也相同,他们的值也相同
  27. child process var is 6, globvar is 7
  28. vfork的执行结果:                                     //vfork函数保证子进程先执行,由于它在父进程地址上运行,所以它先对两个变量的改变对于
  29. now var is 5 ,globvar is 6                          //父进程是可见的,子进程运行完之后,父进程得到已经被改变一次的变量值继续运行。
  30. child process var is 6, globvar is 7
  31. father process var is 7, globvar is 8

fork()函数的一瞬间全局变量和局部变量已经被子进程继承,以后他们运行在不同的地址空间,父进程更改,对于子进程是不可见的。

vfork()函数虽然子进程运行在父进程的地址空间上,但是vfork()保证了子进程的优先运行,应此父进程更改全局变量,子进程看不到。

阅读(1) | 评论(0) | 转发(0) |

给主人留下些什么吧!~~
评论热议

版权声明:本文为博主原创文章,未经博主允许不得转载。

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. CF1322B-Present【双指针】

    正题 题目链接:https://www.luogu.com.cn/problem/CF1322B 题目大意 给出\(n\)个数字\(a_i\)求 \[\bigoplus _{i=1}^n\bigopl ...

  2. SQL Server附加数据库错误5120处理方法

    SQL Server附加数据库5120错误 当我们从另外一台服务器复制过来的数据库,可能会有如下错误: 解决方法 1.给数据库所在文件夹增加用户Everyone并赋予完全控制权限 2.以管理员身份运行 ...

  3. 从产业链、架构和技术三个层面,看元宇宙与RPA的发展关系

    你可能还不知道,元宇宙也将带动RPA高速发展 一文读懂RPA如何赋能元宇宙,虚拟空间更需要RPA无处不在 三个层面,解读元宇宙如何利好RPA行业发展 从产业链.架构和技术三个层面,看元宇宙与RPA的发 ...

  4. mysql从零开始之MySQL UPDATE 更新

    MySQL UPDATE 更新 如果我们需要修改或更新 MySQL 中的数据,我们可以使用 SQL UPDATE 命令来操作. 语法 以下是 UPDATE 命令修改 MySQL 数据表数据的通用 SQ ...

  5. Jmeter使用问题记录

    Jmeter下载安装,设置中文,返回值乱码处理,下载接口测试 下载地址 解压后,在Jmeter的bin文件夹下启动 修改默认启动为中文简体:打开bin目录下的jmeter.properties文件,在 ...

  6. Data Management Tools(数据管理工具)《一》

    数据管理工具 1.LAS数据集 # Process: LAS 数据集统计数据 arcpy.LasDatasetStatistics_management("", "SKI ...

  7. NOI2018屠龙勇士(扩展CRT + splay(multiset))

    QWQ 一到假期就颓废 哎 今年新鲜出炉的NOI题,QwQ同步赛的时候写的,后来交了一发洛谷,竟然过了 首先 根据题目,我们很容易得到,假设对应每一条龙的剑的攻击力是\(atk\)的话 \[a_i-x ...

  8. Perl操作excel2007的模块

    详细版:https://www.jianshu.com/p/84bda53827c8 第一种方法: 读写excel2007文档的perl模块: Spreadsheet::XLSX(读)和Spreads ...

  9. 4.1 The Example Domain 领域示例代码

    4.1 The Example Domain 领域示例代码 The examples will use some concepts those are used by GitHub, like Iss ...

  10. 2.3 Core Building Blocks 核心构件

    Core Building Blocks 核心构件 DDD mostly focuses on the Domain & Application Layers and ignores the ...