-
系统编程第三天
前两天将描述符讲完了,但是还不会用,今天老师讲的是关于进程的内容,今天终于拿到老师敲的代码了,要不然没有参考代码真的很难写,按照现在的情况,真的很难做到现学现卖",经常对刚讲的内容没印象,突然让写代码都不知道如何下手,还好现在有参考的了。
一、执行流:按照顺序执行的一段代码被称为执行流,在多任务操作系统环境下,执行流被分为:
- 任务流:
a. 进程(process)
b. 线程(thread) - 异常流:操作系统负责这些代码
二、进程(process):正在执行的应用程序
可执行文件被执行变成进程的过程(即程序启动过程):
1). 二进制指令读到内存中去
2). 系统自动执行全局变量和静态局部变量定义语句
3). 调用本程序的main函数进程退出方法:
1). main函数返回
2). exit:不建议使用
atexit
3). abort:不允许使用多任务操作系统,需要管理很多个进程:
1). 每个进程有个唯一身份标识:pid
2). 进程之间存在着父子关系
3). 操作系统启动后运行的第一个进程被称为祖先进程(init)
4). ps -ef:查看所有已经运行的任务正在等待获得CPU时间片任务,可以查看ppid
ps -aux: 查看所有已经运行的任务,可以查看任务状态
ps -a:只能查看从当前控制台运行起来的任务
5). OS定义了一个结构体来描述进程的各种属性,这样的一个结构体类型对象被称PCB(Process Control Block)
6). 任务的五个状态:
就绪态:任务正在等待获得CPU时间片
运行态:任务代码正在被CPU执行
睡眠态:任务处于等待资源就位或某个条件成立的状态
僵死态:任务已经终止但是所占资源还未被回收的状态
暂停态:任务处于暂时停止后续还可以继续执行的状态
7). 僵尸进程:处于僵死状态的进程
8). 孤儿进程:其父进程已经终止,但本身还没有被祖先进程init领养的进程,这样的进程不会一直是孤儿,它们很快会被祖先进程init领养-
fork函数
- 处理过程如下:
a. 复制父进程PCB
b. 分别处理三类属性:
a). 必须修改的(pid ppid)
b). 自己独有但是继承父进程的初始值(栈区、数据区、堆区、文件描述符)
c). 与父进程共用(代码区) - 调用模板:
- 处理过程如下:
pid_t pid;
pid = fork();
if(pid < 0)
{//出错
}
else if(0 == pid)
{//子进程才执行代码
//......
}
else
{//父进程才执行代码
//.....
}
//......后续代码
- exec函数:替换当前进程
1).exec开头的函数将替换当前进程为指定新的程序,新的程序将从自己main开始运行,直到结束。当前进程自此将拥有独立的代码区
2). int execl(const char *path, const char *arg0,…,(char*)0);
path为带路径的可执行文件名
arg0为给指定程序main函数的argv[0]参数
arg1为给指定程序main函数的argv[1]参数
......
最后一个参数必须写NULL
3).int execlp(const char *file, const char *arg0,…,(char*)0);
file为不带路径的可执行文件名(用于可执行文件在PATH环境变量指定的目录中))
arg0为给指定程序main函数的argv[0]参数
arg1为给指定程序main函数的argv[1]参数
......
最后一个参数必须写NULL
```
6. 等待进程终止
1) wait函数:等待任一子进程终止
pid_t wait(int *status);
waitpid函数:等待指定子进程终止
pid_t waitpid(pid_t pid, int *status, int options);//options一般填0
这两个函数将做如下3件事:
a)等待某一个子进程终止
b)获取子进程退出的一些信息到status指向的空间(如main函数返回值)
c)为已终止的子进程做善后处理(即回收子进程所占用的内存资源)
作业:
1) 编写程序完成如下功能:
子进程负责:向文件f.txt中写入内容"Hello Process"
父进程负责:子进程退出后,从f.txt中读出内容,并显示出来