代码分析

关于fork()函数的疑问

1、调用一次,返回两次。
fork函数被父进程调用,当前的父进程是哪个进程?返回两次,什么叫返回两次?同样的代码运行两次吗?
2、相同的但是独立的地址空间。
在返回两次,子进程和父进程都是再次从main()函数进入重新执行吗?
3、并发执行
并发执行是cpu随意指定,想先运行哪个就是哪个?

p493页代码分析
#include "csapp.h"int main()
{pid_t pid;int x = 1;pid = Fork(); //返回两个进程,pid=2780;printf("pid %d\n",pid);if (pid == 0) {  //子进程返回的pid为0;父进程返回子进程的pid;printf("child : x=%d\n", ++x); exit(0);}printf("parent: x=%d\n", --x); exit(0);
}

结果显示:

  • 调用一次返回两次:
    在语句pid = Fork();之前,只有一个进程在执行这段代码,但在这条语句之后,就变成两个进程在执行了,这两个进程的几乎完全相同,将要执行的下一条语句都是
printf("pid %d\n",pid);
if (pid == 0)

如果fork返回的pid>0表示当前运行进程为父进程,若pid==0,则表示当前进程为子进程;

  • 有独立的地址空间:父子进程都是在x=1基础上进行运算,父进程执行后x=0;子进程x=2。
forkdemo2.c
#include <stdio.h>
#include <unistd.h>int main()
{int pid1,pid2;printf("before:my pid is %d\n", getpid() );pid_t pid1=fork();pid_t pid2=fork();printf("我的父亲pid是:%d,我的pid是: %d,我的儿子pid是:\n", getppid(),getpid(),pid1);return 0;
}

结果显示:

  • 分析代码,会返回4个进程,但是最后printf后的三个子进程的父进程的pid均是1351,后经过查阅资料,在这里涉及到进程的死亡。在第一次父进程printf结束后,父进程死亡,但是子进程不能没有父进程,所以将他们的父进程改到1351。ps -A查看1351是upstart进程。

exec函数

在分析代码前需要知道:

fork函数是用于创建一个子进程,该子进程几乎是父进程的副本,而有时我们希望子进程去执行另外的程序,exec函数族就提供了一个在进程中启动另一个程序执行的方法。它可以根据指定的文件名或目录名找到可执行文件,并用它来取代原调用进程的数据段、代码段和堆栈段,在执行完之后,原调用进程的内容除了进程号外,其他全部被新程序的内容替换了。

在Linux中并没有exec函数,而是有6个以exec开头的函数族

  • 查找方式:以p结尾的两个函数可以只给出文件名,系统就会自动从环境变量“$PATH”所指出的路径中进行查找。

  • 参数传递方式:参数传递方式是以函数名的第5位字母来区分的,字母为“l”(list)的表示逐个列举的方式,字母为“v”(vertor)的表示将所有参数整体构造成指针数组传递,然后将该数组的首地址当做参数传给它,数组中的最后一个指针要求是NULL。

  • 环境变量:exec函数族使用了系统默认的环境变量,也可以传入指定的环境变量。这里以“e”(environment)结尾的两个函数execle、execve就可以在envp[]中指定当前进程所使用的环境变量替换掉该进程继承的所以环境变量

execvp函数
int main()
{char    *arglist[3];arglist[0] = "ls";arglist[1] = "-l";arglist[2] = 0 ;//NULLprintf("* * * About to exec ls -l\n");execvp( "ls" , arglist );//只给出文件名ls,参数整体构造成指针数组传递printf("* * * ls is done. bye");//结束后不返回到主进程中,不打印该句。return 0;
}

env

getenv()函数(取得环境变量内容)
  • 定义函数 char * getenv(const char *name);
  • 函数说明 getenv()用来取得参数name环境变量的内容。参数name为环境变量的名称,如果该变量存在则会返回指向该内容的指针。环境变量的格式为name=value。
  • 返回值:执行成功则返回指向该内容的指针,找不到符合的环境变量名称则返回NULL。
setenv()函数(改变或增加环境变量)
  • 定义函数 int setenv(const char name,const char value,int overwrite);name为环境变量名称字符串。 参数 value则为变量内容。
  • 函数说明 setenv()用来改变或增加环境变量的内容。
  • 参数 overwrite用来决定是否要改变已存在的环境变量。如果overwrite不为0,则改变环境变量原有内容,原有内容会被改为参数value所指的变量内容。如果overwrite为0,且该环境变量已有内容,则参数value会被忽略。
  • 返回值 执行成功则返回0,有错误发生时返回-1。  错误代码 ENOMEM 内存不足,无法配置新的环境变量空间
#include <stdio.h>
#include <stdlib.h>int main(void)
{printf("PATH=%s\n", getenv("PATH"));setenv("PATH", "hello", 0);//overwrite=0,不改变path的值printf("PATH=%s\n", getenv("PATH"));
#if 1printf("PATH=%s\n", getenv("PATH"));setenv("PATH", "hellohello", 1);//path=hellohelloprintf("PATH=%s\n", getenv("PATH"));printf("MY_VER=%s\n", getenv("MY_VER"));//新的一个环境变量名称。MY_VER=null;setenv("MY_VER", "1.1", 0);//虽然overwrite=0,但是由于该变量无内容,所以最后MY_VER=1.1;printf("MY_VER=%s\n", getenv("MY_VER"));
#endifreturn 0;
}

pipe函数?

关于pipe函数,看上去很简单,但实际上我个人感觉是问题最多的一个。pipe相当于一个管道,从一端读文件,一端用来写文件,如果和fork函数配套使用的话,不是应该父进程(或者子进程)只能读,剩下一个只能写吗,为什么程序中父进程和子进程同时拥有读和写的功能close( filedes[0] ); close( filedes[1] );。查阅众多资料后,终于明白了。上代码分析:

#define oops(m,x)   { perror(m); exit(x); }int main(int ac, char **av)
{int thepipe[2],         newfd,              pid;                if ( ac != 3 )//如果输入的命令的字符!=3,提示用法为:pip  cmd1 cmd2.{fprintf(stderr, "usage: pipe cmd1 cmd2\n");exit(1);//提出程序}if ( pipe( thepipe ) == -1 )    //建立管道  oops("Cannot get a pipe", 1);if ( (pid = fork()) == -1 )//fork建立有血缘关系的两个进程。          oops("Cannot fork", 2);if ( pid > 0 )//父进程{ close(thepipe[1]);//使父进程关闭写的一端,只能读  if ( dup2(thepipe[0], 0) == -1 )//将输入重定向为标准输入oops("could not redirect stdin",3);close(thepipe[0]);//关闭读的一端  execlp( av[2], av[2], NULL);oops(av[2], 4);}close(thepipe[0]);//子进程关闭读的一端,只能写       if ( dup2(thepipe[1], 1) == -1 )//将管道输出端重定向为标准输出oops("could not redirect stdout", 4);close(thepipe[1]);      execlp( av[1], av[1], NULL);oops(av[1], 5);
}
  • 管道通信是单向的,并且遵守先进先出的原则,即先写入的数据先读出。
  • 管道是一个无结构,无固定大小的字节流。
  • 管道把一个进程的标准输出和另一个进程的标准输入连接在一起。数据读出后就意味着从管道中移走了,消失了。其它的进程都不能再读到这些数据。就像我们平常见到的管子水流走了就没有了。

学习进度条

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
目标 3500行 30篇 400小时
第一周 40/40 1/1 20/20
第二周 30/70 1/2 30/50
第三周 21/91 1/3 28/78
第五周 131/222 1/4 20/98
第六周 32/254 1/5 21/119
第七周 200/454 1/5 21/119
第八周 0/454 2/7 10/129
第九周 84/538 2/9 15/144
第10周 441/979 2/11 10/154
第11周 460/1439 2/13 20/174
第11周 300/1739 2/15 20/194

代码托管

代码链接

参考资料

  • Linux基础入门
  • Linux下C语言开发基础
  • ...

转载于:https://www.cnblogs.com/yayaer/p/6117252.html

20145204 张亚军《信息安全系统设计基础》第12周学习总结相关推荐

  1. 20145309信息安全系统设计基础第12周学习总结后篇

    指针与声明 声明 1.C语言中变量的声明 类型(type) 声明符(declarator) 2.最简单的声明是变量 3.指针数组 指针数组是一个数组 数组里的元素都是指针 例:int *daytab[ ...

  2. 20135203齐岳 信息安全系统设计基础第十三周学习总结

    20135203齐岳 信息安全系统设计基础第十三周学习总结 学习计时:8/9共小时(计划/实际) 读书:4/5 代码:1/1 作业:1/1 博客:2/2 第十二章 并发编程 一.学习目标 掌握三种并发 ...

  3. 20135219洪韶武——信息安全系统设计基础第五周学习总结

    信息安全系统设计基础第五周学习总结 学习任务:教材第四章[处理器体系结构] 学习时间:10小时  一.教材知识点梳理[4.1-4.3] 1.ISA[指令集体系结构] 一个处理器支持的指令和指令的字节级 ...

  4. 2018-2019-1 20165221 《信息安全系统设计基础》第一周学习总结

    2018-2019-1 20165221 <信息安全系统设计基础>第一周学习总结 教材学习总结 有关vim 打开方式:vim [文件名] 按i会进入insert模式,可以对代码进行编辑 按 ...

  5. 20135203齐岳 信息安全系统设计基础第五周学习总结

    20135203齐岳 信息安全系统设计基础第五周学习总结 学习计时:共10小时 读书:5 代码:1 作业:2 博客:2 第四章 处理器体系结构 一.学习目标 本章内容是处理器体系结构,重点掌握ISA, ...

  6. 20135219洪韶武——信息安全系统设计基础第十一周学习总结

    信息安全系统设计基础第十一周学习总结 学习时间:10小时 学习内容:课本第八章  一.重点内容 1.重点理解异常的概念.种类.问题处理 (1)控制流的概念 从处理器加点开始,直到断点为止,PC假设一个 ...

  7. # 2017-2018-1 20155224 《信息安全系统设计基础》第九周学习总结

    2017-2018-1 20155224 <信息安全系统设计基础>第九周学习总结 教材学习内容总结 存储器 随机访问存储器(RAM): 静态RAM:用来作为高速缓存存储器,每个位存储在一个 ...

  8. 2018-2019-1 20165206 《信息安全系统设计基础》第九周学习总结

    - 2018-2019-1 20165206 <信息安全系统设计基础>第九周学习总结 - 教材学习内容总结 计算机系统的主存被组织成一个由M个连续的字节大小的单元组成的数组.每个字节都有一 ...

  9. # 20155337 2017-2018-1 《信息安全系统设计基础》第一周学习总结

    20155337 2017-2018-1 <信息安全系统设计基础>第一周学习总结 教材学习内容总结 1.1信息就是位+上下文 hello.c程序是以字节序列的方式储存在文件中的.每个字节都 ...

  10. 20145227《信息安全系统设计基础》第一周学习总结

    20145227<信息安全系统设计基础>第一周学习总结 学习内容总结 Linux是一个操作系统.如果使用GUI,Linux和Windows没有什么区别.Linux学习应用的一个特点是通过命 ...

最新文章

  1. 83篇文献、万字总结开启你的强化学习之路!
  2. Matlab编程序设计数字滤波器
  3. python 多进程同步通信
  4. python界面翻译-我用40行python代码写一个桌面翻译器,很nice
  5. LTE之MIMO学习1-TB/codeword/layer/precoding/port
  6. 安卓ssr无网络连接_解决Android模拟器网络问题(使用了代理的情况下)
  7. 模板模式在源码中的体现
  8. 一些知名的J2me优秀开源UI项目
  9. 求数组第二大元素 和 字符串拷贝的实现
  10. tcp协议和udp协议区别_TCP和UDP协议有什么区别?
  11. 二叉树递归非递归遍历,层次遍历,反转,输出路径等常见操作详细总结
  12. 小马Win7永久激活工具—OemY3.1 NT6通用完美激活
  13. 计算机专业数学建模结课论文,数学建模论文范文2篇
  14. 忘记密码怎么卸载和删除网维大师~
  15. 第三章 高频谐振功率放大器(关键点:功率、效率)
  16. 杭州电子科技大学计算机非全日制,杭州电子科技大学非全日制研究生考试难吗?...
  17. 零基础搭建外卖优惠券返利CPS小程序教程
  18. RestTemplate设置Headers
  19. 手机图片转换成文字怎么办
  20. 多核芯片间的核间通信IPC机制

热门文章

  1. Unity与 SO 交互 ☀️| .so文件(动态链接库 ) 基础知识科普
  2. idea maven项目的依赖有红色波浪线解决
  3. 2021年电工(初级)考试报名及电工(初级)模拟考试题库
  4. 在VSCode中配置并调试R语言.r文件
  5. [经验技巧] 路由mini安装OpenWRT源的Transmission插件,实现PT下载(需SSH)
  6. JavaScript 类的三部曲(二)
  7. Unity 项目游戏退出代码
  8. python京东自动签到_Python 实现京东自动签到领京豆
  9. JDK里的“SPI”是什么意思
  10. Python爬虫实战,完整的思路和步骤(附源码)