一、认识冯诺依曼系统:
- 常见的计算机,如笔记本。我们不常见的计算机,如服务器,大部分都遵守冯诺依曼体系。
截至目前,我们所认识的计算机,都是有一个个的硬件组成
输入单元:键盘,鼠标,扫描仪,写板等
中央处理器:含运算器和控制器
- 所有的外设都只能和存储器打交道。
- cpu也只能和存储器打交道。
- 所以内存起着很重要的作用。
为什么要有存储器?输入设备和输出设备不与cpu直接连接?
cpu运行速度极快,输入设备和输出设备运行速度极慢,存储器介于两者之间。(成指数级别的差距,所以需要存储器来进行缓冲)
为什么程序运行起来必须得先加载到内存里面?
程序运行必须通过cpu调用,cpu只能和内存打交道
二、操作系统:(OS)
任何计算机体系都包含一个基本的程序集合,称之为操作系统
包括:
- 内核(进程管理、内存管理、文件管理、驱动管理)
- 其他程序(例如函数库,shell程序等)
设计OS的目的:
与硬件交互,管理所有的软硬件资源
为用户程序(应用程序)提供一个良好的执行环境
操作系统是搞管理的,管理者和被管理者并不直接冲突
管理者是通过数据对被管理者进行管理决策
- 由操作系统提供的接口叫做系统调用
- 对系统调用进行适度封装,从而形成库
- 库调用系统,库调用接口在上,系统调用接口在下
三、进程
- 当程序从硬盘外设通过冯诺依曼系统加载到内存,此时程序叫做进程。
- PCB描述进程
把描述进程的所有信息的那条记录叫做PCB(process control block)
linux下的PCB:task_struct:存放在/usr/src/kernels/2.6.32-431.el6.i686/include/linux/sched.h
- 优先级:相对于其他进程的优先级。
- 程序计数器:程序中即将被执行的下一条指令的地址。
- 内存指针:包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块指针。
怎么算这个进程在系统中是否被拿走了?
- 1、把现在所占用用的资源让了
- 2、抹掉这个进程的信息
如何删掉一个进程?
- 进程在内存中主要是 代码和数据 还有信息
- 1、把代码和数据 还有信息拿掉,2、把对应的pcb拿掉。
windows怎么管理进程?
和linux一样
拓展:
- 1、硬件中断技术的出现,进而软件片上有了分时系统,时间片轮转。
- 2、进程:
从用户角度看:进程是程序的一次动态执行过程。
从操作系统角度看:
1)进程是操作系统分配内存,cpu时间片等系统资源的基本单位。
2)每个进程有自己独立的虚拟地址空间和进程状态。
3)进程是分配资源的最小单位。 - 3、程序:为了执行特定任务的一系列指令的有序集合。
4、进程是程序的一次执行过程,需要保存进程的现场信息,这些信息需要一个数据结构来保存,在c语言中用结构体,我们将这个结构称之为PCB(process control block) PCB是操作系统感知一个进程存在的重要数据结构。
5、程序:代码段+数据段
进程:代码段+数据段+堆栈+PCB
PCB {
pc 下一条指令的地址
esp 栈顶指针
ebp 基址
}
6、进程和程序的区别:
1)进程是动态的,程序是静态的
2)进程是短暂的,程序是永久的
3)进程有PCB
4)一个进程只能对应一个程序,一个程序可以对应多个进程
查看进程:
方法一:
方法二:
cwd当前工作目录
exe绝对路径
方法三:
方法四:
杀死一个进程:
查看正在运行时的进程:
多次运行后子进程就会发生改变
等待进程结束后就查看不到了:
列出
获取子进程和父进程,多次运行后,发现父进程一直不变,子进程每次都做相应的改变:
通过系统调用创建进程-fork初识
1 #include<stdio.h>
2 #include<sys/types.h>
3 #include<unistd.h>
4 int main()
5 {
6 int ret=fork();
7 if(ret<0)
8 {
9 perror("fork");
10 return 1;
11 }
12 else if(ret==0)
13 {
14 printf("I am child:%d!,ret :%d\n",getpid(),re t);
15
16 }
17 else//father
18 {
19 printf("I am father:%d!,ret:%d\n",getpid(),re t);
20 }
21 sleep(1);
}
验证了若一个子进程创建成功,父进程会返回一个子进程id,子进程返回0。
进程状态
- R运行状态:并不意味着进程一定在运行,它表明进程要么是在运行队列里。
- S睡眠状态:意味着进程在等待事件完成(睡眠也叫可中断睡眠)。
- D磁盘休眠状态:有时也叫不可中断睡眠状态,在这个状态的进程可以通过发送SIGCONT信号让进程继续运行。
- X死亡状态:这个状态只是一个返回状态,你不会在任务列表里看到这个状态。
Z-僵尸进程
- 僵尸状态:当进程退出并且父进程(使用wait()系统调用)没有读取到子进程退出的返回代码时就会产生僵尸(死)进程。
- 僵尸进程会以终止状态保持在进程表中,并且会一直等待父进程读取退出状态代码。
- 所以,只要子进程退出,父进程还在运行,但父进程没有读取进程状态,子进程进入Z状态。
查看僵尸进程:
第一个终端:
第二个终端:
僵尸进程危害:
- 1)子进程一直处于Z状态。
- 2)Z状态一直不退出,PCB一直都要维护。
- 3)造成内存资源的浪费。
- 4)会造成内存泄漏。
孤儿进程:
- 父进程先退出,子进程就称之为“孤儿进程”
ps axj
父进程为1的为孤儿进程
进程优先级
- 查看系统进程:
修改进程优先级的命令:
- renice:调整已存在进程的nice :renice -5 -9 5200
- nice:启动进程前调整nice :nice -n -5 ./a.out
用top命令更改已存在进程的nice;
四、环境变量:
常见的环境变量
PATH: 指定命令的搜索路径
HOME:指定用户的主工作目录(即用户登陆到Linux系统时,默认的目录)
- HISTSIZE:指保存历史命令记录的条数
- SHELL:当前Shell,它的值通常是/bin/bash
查看环境变量方法:
root和普通用户分别执行echo $HOME
- echo $NAME: 你的环境变量名称
- 1、echo:显示某个环境变量值
- 2、export:设置一个新的环境变量
- 3、env:显示所有环境变量
- 4、unset:清除环境变量
- 5、set:显示本地定义的shell变量和环境变量
通过代码如何获取环境变量: - 命令行第三个参数
#include<stdio.h>
2 int main(int argc, char *argv[],char* env[])
3 {
4 int i=0;
5 for(;env[i];i++)
6 {
7 printf("%s\n",env[i]);
8 }
9 return 0;
10 }
通过第三方变量environ获取
1 #include<stdio.h>
2 int main(int argc,char *argv[])
3 {
4 extern char **environ;
5 int i=0;
6 for(;environ[i];i++)
7 {
8 printf("%s\n",environ[i]);
9 }
10 return 0;
11 }
通过系统调用获取或设置环境变量
- putenv
- getenv
1)设置环境变量: int putenv(const char*str) str的格式:”name=value”
2)获得环境变量:
1 #include<stdio.h>
2 #include<stdlib.h>
3 int main()
4 {
5 printf("%s\n",getenv("PATH"));
6 return 0;
7 }
环境变量通常是具有全局属性,可以被子进程继承下去
1 #include<stdio.h>
2 #include<stdlib.h>
3 int main()
4 {
5 char* env=getenv("MYENV");
6 if(env)
7 {
8 printf("%s\n",env);
9 }
10 return 0;
11 }
环境变量
定义变量: name=value # 等号左右不能有空格
删除变量: unset name- 1、直接运行出不来结果,说明该环境变量不存在
- 2、如果只进行MYENV=”hello world”,不调用export导出,不会出现结果
- 3、导出环境变量 export MYENV=“hello world” ,再运行就出现hello world,说明环境变量是可以被子进程继承下去的
- 本地变量只能在当前进程使用。
set:打印更多的变量
env;只打印环境变量
export:把普通变量导成环境变量 export name
只要把可执行程序移到/bin目录下,就可以不加./直接运行。
拓展:
1、pstree | grep -A2 -B2 bash 树状打印bash进程的前两行和后两行
2、问题:
1)、系统有那些环境变量?
env 命令
2)、将自己定义的环境变量放在哪里? 终端打开就存在该环境变量
登录shell之前,会执行~/.bash_profile 文件,本用户的配置
/etc/profile 整个系统所有 所有用户的配置