程序:为了执行特定任务的一系列指令的有序集合
单道程序设计 时钟中断 ——> 进程
多道程序设计 分时系统
1.硬件中断技术的出现,进而软件上有了分时系统,时间片轮转
2.进程:从用户角度看,进程就是程序的一次动态执行过程
3.从操作系统(内核)的角度看,
(1)进程是操作系统分配内存,cpu时间片等系统资源的基本单位(硬盘不算)
(2)每个进程有自己独立的虚拟地址空间和进程状态
(3)进程是分配资源的最小单位
4.进程是程序的一次执行过程,需要保存进程的现场信息,这些信息需要一个数据结构来保存,在c语言中用结构体,我们将这个结构称为PCB(process control block)。
5.PCB是操作系统感知一个进程存在的重要数据结构。
6.程序:代码段+数据段。
7.进程:代码段+数据段+堆栈+PCB
pc:下一条指令的地址
esp:栈顶指针
ebp:基址
PCB将代码和有效数据的粘合在一起。
进程和进程的区别:
1).进程是动态的,程序是静态的。
2).进程是短暂的,程序是永久的。
3).进程有PCB
4).一个进程只能对应一个程序,一个程序可以对应多个进程。
(https://img-blog.csdn.net/20180412182839582?watermark/2/text
/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2xjNTc4NjI2
/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
awk ‘{print }’filena
查看进程信息:ps aux (睡眠态) ps aux |grep aplay| grep -v grep | awk ‘{print $2}’
kill -l
状态变迁:
三态
liunx七态
ps查看进程状态
ps aux /ps -ef
(https://img-blog.csdn.net/201804121835026?watermark/2/text/
aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2xjNTc4NjI2
/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
liunx对应的PCB数据结构:task_struct 保存以下内容
进程标识符
进程状态
进程优先级
各种时间信息
进程间通信信息
内存使用情况
寄存器的信息(也叫保存现场)
内存使用情况:
https://img-blog.csdn.net/
20180412183713534?watermark/2/text/
aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2xjNTc4NjI2
/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
进程标识符:
操作系统会给每个进程分配一个独一无二的编号。
编号的范围:[2,cat /proc/sys/kernel/pid_max]
0是内核进程
0号进程启动1(init)号进程。
swap分区。
创建进程的一般过程:
给新建的进程分配一个进程标识符,在内核中创建PCB,
复制父进程的环境。(新的进程为子进程)
给子进程分配资源,栈,堆,代码,数据等。
拷贝父进程的地址空间内容到子进程的地址空间
将进程置为就绪态,放到就绪队列。
在proc 的下:cat maps 查看进程分配情况。
创建子进程:
pid _t fork(void)
父进程返回进程ID,子进程返回0。
附加:
错误处理
1.若干个if else
2.定义一个errno,所有的系统调用出错都返回-1,然 后将错误编号记录到errno中
通过strerror得到错误编号对应的描述
获得子进程ID
pid_t getpid(void)
获得父进程ID
pid_t getppif(void)
fork的注意点:
1.fork之后,父子进程交替运行
2.如果父进程死亡,子进程活着,叫孤儿进程。孤儿进程托管给1号进程,1号进程也叫孤儿院。
3.如果父进程活着,子进程死亡,子进程就是一个僵尸进程。僵尸进程会占用少量系统资源。僵尸进程是有害的。
弄死进程的方法:
1.ctrl + c 2.kill pid 3.kill -9 pid(杀人不眨眼的) kill 不能杀死僵尸进程
进程被虚拟文件:
进程优先级:/proc/pid
1.nice -n 优先级 程序名(优先级 -20——19)
2.renic 优先级 -p 进程名
3.top shift+>/< 翻屏 r pid
写时拷贝:
没有必要全部拷贝一份,父子进程什么时候修改,什么时候拷贝一份出来。称之为写时拷贝。
vfork 第二个创建子进程函数:
pid_t pid = vfork()
特点:
1.父进程阻塞,直到子进程运行完毕。
2.就算写时,也不拷贝
3.必须使用exit/exec
4.每个系统堆=对vfork的实现或多或少都有问题,不要使用
traceroute www.baidu.com
销毁进程的过程:
1.释放资源。(内存,文件等等)
2.记账信息。
3.将进程设置为僵尸状态。
4.转存储调度。(将CPU让给需要使用的进程)
进程退出的方法:
正常退出:
1.main函数退出。
2.exit
异常退出:
1.ctrl + c
2.abort(函数)
3.kill
所有不正常死亡都是由信号引起。
![这里写图片描述](https://img-blog.csdn.net/20180412184022734?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2xjNTc4NjI2/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
退出时执行注册函数
int on_exit(void (*function)(int , void *), void *arg);
int on_exit(void (*function)(int , 是退出码
void *),
void *arg) //退出处理函数参数
等待进程:
pid_t wait(int *status);
//阻塞,直到有子进程退出才返回。status参数会得到子进程是如何死亡的。
//返回值:被回收的子进程ID,出错,返回-1.
WIFEXITED(status) 如果正常退出,返回真
WEXITSTATUS(status) 如果正常退出,得到退出码
WIFSIGNALED(status) 如果信号被打断,返回真
WTERMSIG(status) 如果是被信号打断,得到信号
pid_t waitpid(pid_t pid, int *status, int options);
pid_t waitpid(pid_t pid,
int *status, //
int options);// 0 WNOHANG
pid > 0;等待进程id等于pid的子进程死亡
pid = 0;调用者进程所在进程组的任何一个子进程死亡
pid = -1;等待任何一个子进程死亡
pid < -1;|pid|进程组的任何一个子进程死亡
进程空间交换:
int execvp(const char *file, char *const argv[]);(替换4G空间)
int execvp(const char *file, //可执行程序名字
char *const argv[]); //main函数的参数
exic不创建新进程、PCB,进程id不会变。
5个函数:
1. int execl(const char *path, const char *arg, ...);
2. int execlp(const char *file, const char *arg;
3. int execle(const char *path, const char *arg,
..., char * const envp[]);
4. int execv(const char *path, char *const argv[]);
5. int execvp(const char *file, char *const argv[]);
v:vector
l:list
p:path
e:environ
补充:
环境变量:
定义变量: name=value 等号左右不能有空格。是一个 本地变量,只能在当前进程里使用。
删除变量:unset name
将本地变量转化为环境变量:
export name
本地变量只能在当前进程使用,环境变量可以在当前进程及子 进程使用。
pstree: 可以将进程的树状结构打印出来。
问题:
1.系统有哪些环境变量
env 查看,history 查看历史命令
2.将自己定义的环境变量放在哪里?终端打开就存在该环境变 量。
登陆shell之前,会执行 ~/.bash_profile 文件,本用户 的配 置/etc/profile 整个系统所有用户的配置。
程序中如何操作环境变量:
设置环境变量:int putenv(const char *str)str 的格 "name=value"
读取环境变量的值:
char *getenv(const char *name)获取一个环境变量。
main函数的第三个参数 int main(int a, char*b[], char*c) 获取所有的环境变量。
01-17
“相关推荐”对你有帮助么?
-
非常没帮助
-
没帮助
-
一般
-
有帮助
-
非常有帮助
提交