1.进程
【1】进程的定义:
进行中的程序
程序的一次执行过程 (内存 + CPU)
程序的实例
【2】
程序 ----加载到内存----> 进程
静态 动态
硬盘 内存
内存 空间 ---- 掉电丢失
【3】进程概念
(用来描述 程序动态执行的过程,方便操作系统管理的)
【4】应用场景:
实现并发
同一时刻 同时发生
2. 进程 的组成
【1】 进程怎么来的?
程序 ---- 加载到内存 ----> 进程
【2】程序的组成:
程序 = 代码 + 数据
程序 = 代码区 + [栈|堆|全局区|字符串常量区]
【3】栈
------|
堆 |
------|
全局区|data/bss data --- 已经初始化了的全局变量或静态变量 bss ---未初始化
------|
代码段|text
【4】进程 = 代码|data|bss|堆|栈 + pcb
pcb (process control block) 进程控制块
PID process id //进程id号
对比:
进程 相当于是 计算机世界中 人
pcb
struct task_struct {
PID, //进程标识符
PPID, //父进程ID号 parent
当前工作路径 //chdir
umask //0002
进程打开的文件列表 //文件IO中有提到
信号相关设置 //处理异步io, ---段错误
用户id,组id
进程资源的上限
}
3.进程的状态:
PROCESS STATE CODES
Here are the different values that the s, stat and state output specifiers
(header "STAT" or "S") will display to describe the state of a process:
D uninterruptible sleep (usually IO) //不可中断的睡眠态
R running or runnable (on run queue) // 运行态
S interruptible sleep (waiting for an event to complete)//可中断的睡眠态
T stopped by job control signal // 暂停态
t stopped by debugger during the tracing
W paging (not valid since the 2.6.xx kernel)
X dead (should never be seen)
Z defunct ("zombie") process, terminated but not reaped by its parent
For BSD formats and when the stat keyword is used, additional characters may be displayed:
< high-priority (not nice to other users)
N low-priority (nice to other users)
L has pages locked into memory (for real-time and custom IO)
s is a session leader
l is multi-threaded (using CLONE_THREAD, like NPTL pthreads do)
+ is in the foreground process group
R --- 运行态
D --- 不可中断 睡眠态
S --- 可中断 睡眠态
T --- 暂停态
Z --- 僵尸态
4.
进程管理的命令:
top //类似Windows的下任务管理器
ps -eLf | head -1 //可以观察到 PID PPID
F S UID PID PPID C PRI NI ADDR SZ WCHAN STIME TTY TIME CMD
ps -eLf | grep a.out //查看a.out 信息 //可以观察到 PID PPID
ps -aux | grep a.out //可以查看进程 的状态
pstree //进程树
pstree -sp pid号 //查看指定的进程的关系
kill //给进程发信号
kill 信号 程序的pid号
eg:
kill -9 5266
kill -l //查看可以发送的信号
5.创建子进程
fork()
pid_t fork(void);
功能:
创建子进程 (通过复制调用进程)
参数:
void
返回值:
成功
在父进程中 返回子进程的pid号
在子进程中 返回0
失败
-1 && errno 被设置
pid号:
pid 本质上就是一个数值
正整数 1
一次调用,会返回两次。
子进程先运行和是父进程先进程,顺序不确定。
变量不共享。
子进程复制父进程的0到3g空间和父进程内核中的PCB,但id号不同。
此时,父子进程各自拥有独立的4g内存空间 (32位的系统)
功能:
通过该函数可以从当前进程中克隆一个同名新进程。
克隆的进程称为子进程,原有的进程称为 父进程。
子进程是父进程的完全拷贝。
复制之后,
子进程和父进程 各自拥有自己的 用户空间(进程空间)
子进程和父进程的执行过程是从fork函数之后执行。
子进程与父进程具有相同的代码逻辑。
返回值:int 类型的数字。
在父进程中:成功 返回值是子进程的pid号 >0
失败 返回-1;
在子进程中:成功 返回值 0
失败 无
注意:
1.创建好之后,父子进程的运行顺序是不确定 ---全部取决于 操作系统的调度
6.kill操作:
将父进程杀死
init进程(1) //UNIX环境高级编程(init -- systemd)
init(1)───gnome-terminal-(2554)───bash(3336)───a.out(5934)───a.out(5935)
init(1)───a.out(5935)
子进程 还在 ,父进程不在 ---- 孤儿进程
---- 此时由init进程 收养
结束子进程,父进程还在,但是父进程并没有对子进程"收尸"
特殊:
孤儿进程
子进程 还在,父进程不在
僵尸进程
子进程 结束,父进程还在,且父进程并未"收尸"
僵尸态进程有危害
练习3:
fork()&&fork()||fork(); //总共几个进程
32 位 --- 地址总线 数据总线
2^32 = 2^10 * 2^10 * 20 ^10 * 2^2
1k 1M 1G * 4
4G空间
注意:
1.父子进程创建好之后,各自拥有独立4G内存空间(32位系统)
2.他们的数据相互独立,父进程或子进程对数据的修改,不会相互影响,只会对各自造成影响
7.应用场合:
1)一个进程希望复制自己,使父子进程同时执行同的代码段。 --- 子承父业
网络服务中会比较多见。(服务器程序,比如,淘宝,接收登录+购物操作)
eg:
12306 网站:
(1).登录
(2).查询车票
订购车票
付款
12306服务器
子进程
子1 --- 1 查询,订购,付款
子2 --- 2 查询,订购,付款
多任务的并发。
2)一个进程需要执行一个不同的程序。//fork + exec --- 独立创业
bash
|--bash_child -- ls/cp/a.out
8.fork出一个子进程。
子进程与父进程做的完全不同的事情。
exec函数族
eg:
minishell
linux@ubuntu:test$ pstree -sp 3210
init(1)───gnome-terminal(2579)───bash(2590)───a.out(3210)───a.out(3211)
bash(2590)
|
fork()
/ \
bash(2590) bash() + exec()//执行了一个与bash完全不用的程序。
//执行了一个新的程序
使用变量测试,验证位于不同的地址空间。
bash(7765)───a.out(12807)───a.out(12808)
bash(7765)
|
fork
/ \
bash(7765) (a.out)bash(7766) //运行了一个 a.out //exec
创建n个进程 :
输入n 创建n个子进程