欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-03-07 20:02:14
...

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

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 计算机管理硬件

(1)先描述起来,用struct结构体;
(2)组织起来,用链表或其他高效的数据结构。

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 概念

(1)实际上也就是虚拟地址空间即操作系统通过mm_struct这个结构体为进程描述一个空间,也称作内存描述符;
(2)通过页表的映射找到物理地址;

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);
  }
}

输出结果

[[email protected] 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
[[email protected] 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;
}

输出结果

[[email protected] 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]
[[email protected] process]$ 
相关标签: 操作系统和网络