操作系统与网络 (4. Linux进程(process))

不期待突如其来的好运,
只希望所有的努力终有回报!

4. Linux进程(process)

4.1 冯诺依曼体系结构
4.1.1 计算机的四个主要结构化部件

(1)处理器(propcessor)

  • 控制计算机的操作,执行数据处理功能,通常指CPU(中央处理器);
  • 通常使用两个内部存储器:存储器地址寄存器(确定下一次读写的存储器地址)和存储器缓冲寄存器(存放要写入存储器的数据或者从存储器中读取的数据);

(2)内存(main memory)

  • 内存通常称为实存储器(real memory)或主存储器(primary memory),存储数据和程
    序;
  • 特点:易失性。

(3)输入输出模块(I/O module)

  • 在计算机和外部环境之间移动数据,外部环境由各种外部设备组成,包括辅助存储器设备
    (如硬盘)、通信设备和终端;

(4)系统总线(system bus)

  • 为处理器、内存和输入/输出模块间提供通信的设施。
4.2 操作系统概念与定位
4.2.1 概念
  • 任何计算机系统都包含一个基本的程序集合,称为操作系统(OS),笼统的理解,操作系统包括:内核(进程管理,内存管理,文件管理,驱动管理)其他程序(例如函数库,shell程序等等)。
4.2.2 设计目的
  • 1.与硬件交互,管理所有的软硬件资源;
  • 2.为用户程序(应用程序)提供一个良好的执行环境。
4.2.3 定位
  • 在整个计算机软硬件架构中,操作系统的定位是:一款纯正的“搞管理”的软件。
4.2.4 系统调用和库函数

(1)定义
系统调用

  • 在开发角度,操作系统对外会表现为一个整体,但是会暴露自己的部分接口,供上层开发使用,这部分由操作系统提供的接口叫做系统调用。

库函数

  • 系统调用在使用上,功能比较基础,对用户的要求相对比较高,所以,有些开发者对部分系统调用进行适度封装,从而形成了库,有了库,就有利于更上层用于或者开发者进行二次开发。

(2)关系

  • 库函数是对系统调用接口的一层封装,是上下级的调用关系。
4.2.5 如何理解管理
  • 管理者并不需要直接与被管理者相互进行管理,而是通过对被管理者进行描述,并且将描述信息得当的,组织起来进行管理。
4.2.6 计算机管理硬件
  • 先描述起来,用struct结构体;
  • 再组织起来,用链表或其他高效的数据结构。
4.3 进程背景与定义
4.3.1 概念
  • 1.从用户层面来说:进程就是运行起来的程序;
  • 2.从操作系统的层面来理解:程序运行需要将代码加载到内存中,操作系统上运行了很多的程序,操作系统必须去管理这些程序的运行,先描述再组织进行管理,在操作系统的层面进程就是操作系统对一个运行的程序的描述。
4.3.2 描述进程-PCB

PCB

  • 进程信息被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的集合。PCB(process control block),Linux操作系统下的PCB是: task_struct 结构体。

task_struct

  • 在Linux中描述进程的结构体叫做task_struct。 task_struct是Linux内核的一种数据结构,它会被装载到RAM(内存)里并且包含着进程的信息。

task_struct的分类

  • (1)标示符: 描述本进程的唯一标示符,用来区别其他进程;
  • (2)状态: 任务状态,退出代码,退出信号等;
  • (3)优先级: 相对于其他进程的优先级;
  • (4)程序计数器: 程序中即将被执行的下一条指令的地址;
  • (5)内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针;
  • (6)上下文数据: 进程执行时处理器的寄存器中的数据[休学例子,要加图CPU,寄存器];
  • (7)I/O状态信息: 包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表;
  • (8)记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等;
  • (9)其他信息。
4.3.3 时间片
  • CPU在每个程序上所运行的这段时间。
4.3.4 CPU的分时机制
  • 轮询法去调度运行一个个程序,目的是为了让所有的程序都能同时推进。
4.4 描述进程
4.4.1 查看进程
  • ps -aux | grep file
  • ps -ef | grep file
4.4.2 通过系统调用

(1)获取进程标识符

  • 进程id(PID);父进程id(PPID)

(2)创建进程fork

  • man fork;fork有两个返回值;父子进程代码共享,数据各自开辟空间,私有一份(采用写时拷贝技术)。
4.5 进程状态
4.5.1 五种状态模型

(1)R运行状态(running)

  • 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。

(2)S睡眠状态(sleeping)

  • 意味着进程在等待时间完成(这里的睡眠有时候也叫做可中断睡眠(interruptible sleep))。

(3)D磁盘休眠状态(Disk sleep)

  • 有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。

(4) T停止状态(stopped)

  • 可以通过发送SIGSTOP信号给进程来停止(T)进程。这个被暂停的进程可以通过发送
    SIGCONT信号让进程继续运行。

(5) X死亡状态(dead)

  • 这个状态只是一个返回状态,不会在任务列表里看到这个状态。
4.5.2 进程状态查看

(1)ps -aux | grep [文件名]
(2)ps -ef | grep [文件名]

4.5.3 僵尸进程Z(zombie)

(1)定义

  • 在fork()/execve()过程中,假设子进程结束时父进程仍存在,而父进程fork()之前既没安装SIGCHLD信号处理函数调用 waitpid()等待子进程结束, 又没有显式忽略该信号,处于僵死状态的进程,则子进程成为僵尸进程。

(2)产生原因

  • 子进程先于父进程退出,因为要保留退出原因,因此操作系统不能直接释放所有资源,通知父进程获取退出原因,允许操作系统释放资源,但是父进程没有关注这个通知导致子进程退出后无法释放所有资源,处于僵死状态成为僵尸进程。

(3)如何避免

  • 进程等待:
  • 父进程调用wait和waitpid来等待子进程的结束,但是这将导致父进程的挂起,浪费资源;

(4)危害场景

  • “擒贼先擒王”
4.5.4 孤儿进程

(1)定义

  • 一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。如果父进程在子进程结束之前退出,则子进程将由init接管。init将会以父进程的身份对僵尸状态的子进程进行处理。

(2)产生原因

  • 父进程先于子进程退出,子进程就会成为孤儿进程,运行在后台,父进程成为1号进程。

(3)如何避免
(4)危害场景

4.5.5 守护进程

(1)定义

  • 守护进程是创建守护进程时有意把父进程结束,然后被1号进程init收养。守护进程会随着系统的启动默默的在后台运行,比如产生了很多的僵尸进程,那么守护进程的职责就是专门杀死父进程,这样就不会有僵尸进程了;类似看门狗程序(防止死机)就是守护进程。

(2)产生原因
(3)如何避免
(4)危害场景

4.6 进程调度
4.6.1 进程优先级
4.6.2 进程竞争性与独立性

(1)竞争性

  • 系统进程数目众多,而CPU资源只有少量,甚至1个,所以进程之间是具有竞争属性的。为了高效完成任务,更合理竞争相关资源,便具有了优先级。

(2)独立性
多进程运行,需要独享各种资源,多进程运行期间互不干扰。

4.6.3 并行与并发

(1)并行

  • 多个进程在多个CPU下分别,同时进行运行,这称之为并行。

(2)并发

  • 多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为并发。
4.7 环境变量
4.7.1 概念
  • 一般是指在操作系统中用来指定操作系统运行环境的一些参数。
  • 例如:我们在编写C/C++代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在哪里,但是照样可以链接成功,生成可执行程序,原因就是有相关环境变量帮助编译器进行查找。
4.7.2 特性
  • 环境变量通常具有某些特殊用途,还有在系统当中通常具有全局特性;
4.7.3 相关命令
  • env/set/echo
4.7.4 接口
  • main的第三个参数/全局变量/envirin/getenv
4.7.5 常见环境变量
  • PATH : 指定命令的搜索路径;
  • HOME : 指定用户的主工作目录(即用户登陆到Linux系统中时,默认的目录);
  • SHELL : 当前Shell,它的值通常是/bin/bash。
4.8 程序地址空间
4.8.1 概念
  • 实际上也就是虚拟地址空间即操作系统通过 mm_struct 这个结构体为进程描述一个空间,也称作内存描述符;通过页表的映射找到物理地址。
4.8.2 程序地址空间和页表的作用
  • 1.提高内存利用率;
  • 2.提供内存访问控制;
  • 3.保证进程的独立性
4.8.3 为什么要使用虚拟地址空间
  • 进程在通过访问地址进而获取变量数据,最终还是要去访问物理内存,因为物理数据是存储在物理内存中,在虚拟地址和物理地址之间通过页表进行地址映射,转换得到物理地址,进而访问到物理内存区域,通过映射之后,物理地址不一定连续,通过这种映射转换的方式实现数据的离散存储提高内存利用率。
4.8.4 操作系统中内存管理

分段式

  • 通过地址中的段号去段表中找到段表项,通过段表中的物理地址加上地址中的段内偏移获取到物理地址。

分页式

  • 通过地址中的页号去页表中找到页表项,通过页表项中的物理页号加上页内偏移获取到物理地址。

段页式

  • 通过段号在段表中找到段表项,通过段表项中的段内页表地址找到段内页表,通过地址中的段内页号在段内也表中找到页表项,通过页表项中的物理页号与页内偏移组成物理地址。
4.9 代码
4.9.1 创建进程
/*===============================================================
 * Copyright (C) . All rights reserved.")"
 * 文件名称:create
 * 创 建 者: yangjie
 * 创建日期: 
 * 描    述: 进程创建
 *           pid_t fork(void);
 *           pid_t vfork(void);
 *           通过复制调用进程, 创建一个新的子进程         
 * =============================================================*/

#include <stdio.h>
#include <unistd.h>

int main()
{
  printf("hello world-----pid:%d\n",getpid());
  // pid_t fork(void);
  // 创建一个子进程, 父进程返回子进程的pid, 子进程返回0
  pid_t pid = fork();
  if(pid < 0 )
  {
    printf("fork error!\n");
    return -1;
  }
  else if(pid == 0)
  {
    printf("-----i am child-----:%d\n",getpid());
  }
  else
  {
    printf("-----i am parent----:%d\n",getpid());
  }
  printf("everything would be better!!!\n");
  while(1)
  {
    printf("Believe yourself!\n");
    sleep(1);
  }
}

输出结果

[dev@localhost process]$ ./create 
hello world-----pid:5629
-----i am parent----:5629
everything would be better!!!
Believe yourself!
-----i am child-----:5630
everything would be better!!!
Believe yourself!
Believe yourself!
Believe yourself!
Believe yourself!
Believe yourself!
Believe yourself!
Believe yourself!
Believe yourself!
Believe yourself!
^C
[dev@localhost process]$ 
4.9.2 环境变量
/*===============================================================
 * Copyright (C) . All rights reserved.")"
 * 文件名称:env
 * 创 建 者: yangjie
 * 创建日期: 
 * 描    述: 这个demo体现环境变量的全局特性
 *          int main(int argc, char* argv[], char* env[])
 * =============================================================*/

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{
  // char* getenv(const char* name);
  // 通过环境变量名获取内容
  // char* ptr = getenv("~");
  // printf("ptr: %s\n",ptr);
  int i;
  extern char** environ;
  for(i = 0; environ[i]!= NULL; i++)
  {
    printf("env[%d]=[%s]\n",i,environ[i]);
  }
  return 0;
}

输出结果

[dev@localhost process]$ ./env 
env[0]=[MANPATH=/opt/rh/devtoolset-4/root/usr/share/man:]
env[1]=[XDG_SESSION_ID=4]
env[2]=[HOSTNAME=localhost.localdomain]
env[3]=[SELINUX_ROLE_REQUESTED=]
env[4]=[TERM=xterm]
env[5]=[SHELL=/bin/bash]
env[6]=[HISTSIZE=4000]
env[7]=[SSH_CLIENT=192.168.136.1 5804 22]
env[8]=[PERL5LIB=/opt/rh/devtoolset-4/root//usr/lib64/perl5/vendor_perl:/opt/rh/devtoolset-4/root/usr/lib/perl5:/opt/rh/devtoolset-4/root//usr/share/perl5/vendor_perl]
env[9]=[SELINUX_USE_CURRENT_RANGE=]
env[10]=[OLDPWD=/home/dev/yangjie/LinuxOSandNET]
env[11]=[JAVACONFDIRS=/opt/rh/devtoolset-4/root/etc/java:/etc/java]
env[12]=[SSH_TTY=/dev/pts/2]
env[13]=[PCP_DIR=/opt/rh/devtoolset-4/root]
env[14]=[USER=dev]
env[15]=[LD_LIBRARY_PATH=/opt/rh/devtoolset-4/root/usr/lib64:/opt/rh/devtoolset-4/root/usr/lib::/home/dev/.VimForCpp/vim/bundle/YCM.so/el7.x86_64]
env[16]=[LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36:]
env[17]=[XDG_CONFIG_DIRS=/opt/rh/devtoolset-4/root/etc/xdg:/etc/xdg]
env[18]=[MAIL=/var/spool/mail/dev]
env[19]=[PATH=/opt/rh/devtoolset-4/root/usr/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dev/.local/bin:/home/dev/bin]
env[20]=[PWD=/home/dev/yangjie/LinuxOSandNET/process]
env[21]=[LANG=zh_CN.UTF-8]
env[22]=[SELINUX_LEVEL_REQUESTED=]
env[23]=[HISTCONTROL=ignoredups]
env[24]=[SHLVL=1]
env[25]=[HOME=/home/dev]
env[26]=[PYTHONPATH=/opt/rh/devtoolset-4/root/usr/lib64/python2.7/site-packages:/opt/rh/devtoolset-4/root/usr/lib/python2.7/site-packages]
env[27]=[LOGNAME=dev]
env[28]=[XDG_DATA_DIRS=/opt/rh/devtoolset-4/root/usr/share:/usr/local/share:/usr/share]
env[29]=[SSH_CONNECTION=192.168.136.1 5804 192.168.136.128 22]
env[30]=[LESSOPEN=||/usr/bin/lesspipe.sh %s]
env[31]=[INFOPATH=/opt/rh/devtoolset-4/root/usr/share/info]
env[32]=[XDG_RUNTIME_DIR=/run/user/1000]
env[33]=[DISPLAY=localhost:12.0]
env[34]=[_=./env]
[dev@localhost process]$ 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值