一、知识点归纳
(一)知识点内容
教材学习内容总结
本章主要讨论Unix/Linux中的进程管理。讲述了多任务处理,以及进程的相关知识:进程的概念;进程创建、终止。还讲到了Unix/Linux进程管理的系统调用:fork()
wait()
exec()
exit()
第一节:多任务处理
在计算机技术中,多任务处理指的是同时执行几个独立任务的能力,是通过在不同任务之间多路复用CPU的执行时间来实现。在单处理器(单CPU)系统中,一次只能执行一个任务。多任务处理是通过在不同任务之间多路复用CPU的执行时间来实现的,即将CPU执行操作从一个任务切换到另一个任务。不同任务之间的执行切换机制称为上下文切换,将—个任务的执行环境更改为另一个任务的执行环境。如果切换速度足够快就会给人一种同时执行所有任务的错觉。这种逻辑并行忡称为 “并发”。在有多个CPU或处理器内核的多处理器系统中,可在不同CPU上实时、 并行执行多项任务。
多任务处理系统
type.h文件
type.h
文件定义了系统常数和表示进程的简单PROC
结构体。
ts.s文件
ts.s
在32位GCC汇编代码中可实现进程上下文切换。
queue.c文件
queue.c
文件可实现队列和链表操作函数。
enqueue()
函数按优先级将PROC
输入队列。在优先级队列中,具有相同优先级的进程按先进先出(FIFO)。
dequeue()
函数可返回从队列或链表中的第一个元素。printlist()
函数可打印链表元素。
t.c文件
t.c
文件定义MT系统数据结构、系统初始化代码和进程管理函数。
第二节:进程
(1)进程的概念
操作系统是一个多任务处理系统。在操作系统中,任务也称为进程。在实际应用中,任务和进程这两个术语可以互换使用。
进程的正式定义:进程是对映像的执行。
(2)进程同步
进程同步是指控制和协调进程交互以确保其正确执行所需的各项规则和机制。
最简单的进程同步工具是休眠和唤醒操作。
睡眠模式:
有时候,进程需要等待直到某个特定的事件发生,例如设备初始化完成、I/O 操作完成或定时器到时等。
在这种情况下,进程则必须从运行队列移出,加入到一个等待队列中,这个时候进程就进入了睡眠状态。
为实现休眠操作,我们可以在 PROC 结构体中添加一个event字段,并实现ksleep(int event)函数,使进程进入休眠状态。
进程睡眠状态有两种:
- 一种是可中断的睡眠状态,其状态标志位TASK_INTERRUPTIBLE
- 另一种是不可中断的睡眠状态,其状态标志位为TASK_UNINTERRUPTIBLE
唤醒操作:
当某个等待时间发生时,另一个执行实体(可能是某个进程或中断处理程序)将会调用 kwakeup(event)。
唤醒正处于休眠状态等待该事件值的所有程序。
如果没有任何程序休眠等待该程序,kwakeup()就不工作,即不执行任何操作。
(3)进程终止
正常终止:
进程调用exit(value),发出_exit(value)系统调用来执行在操作系统内核中的kexit(value)。
异常终止:
进程因某个信号而异常终止。
第三节:I/O重定向
(1)文件流和文件描述符
每个文件流都是指向执行映像堆区中FILE
结构体的一个指针。每个文件流对应Linux内核中的一个打开文件。每个打开文件都用一个文件描述符(数字)表示。
(2)文件流I/O和系统调用
当进程执行库函数
scanf("%s", &item);
它会试图从stdin文件输入一个(字符串)项,指向FILE结构体。如果FILE结构体的fbuf[]
第四节:管道
管道是用于进程交换数据的单向进程间通信通道。管道有一个读取端和一个写入端。可从管道的读取端读取写入管道写入端的数据。
(1)管道命令处理
在Unix/Linux中命令行
cmd1 | cmd2
包含一个管道符号 “ | ” 。
(2)命名管道
命名管道又叫做FIFO。它们有“名称”,并在文件系统中以特殊文件的形式存在。
示例:
①在sh中,通过mknod命令创建一个命令管道:
②或者在C语言中发出mknod()系统调用
③进程可像访问普通文件一样发个文命名管道。
第五节:Unix/Linux进程管理中的系统调用
(1)fork()
函数原型:
pid_t fork(void);
(pid_t 是一个宏定义,其实质是int 被定义在 #include <sys/types.h> 中)
返回值:若成功调用一次则返回两个值,子进程返回0,父进程返回子进程ID;否则,出错返回-1。
在fork函数执行完毕后,如果创建新进程成功,则出现两个进程,一个是子进程,一个是父进程。
在子进程中,fork函数返回0,在父进程中,fork返回新创建子进程的进程ID。通过fork返回的值来判断当前进程是子进程还是父进程。
(2)等待()
函数原型:
int wait(int *status);
父进程一旦调用了wait就立即阻塞自己,由wait自动分析是否当前进程的某个子进程已经退出,如果让它找到了这样一个已经变成僵尸的子进程,wait就会收集这个子进程的信息,并把它彻底销毁后返回;如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止。
(3)执行()
函数原型:
#include <unistd.h>
int execl(const char *pathname, const char *arg0, ... /* (char *)0 */ );
int execv(const char *pathname, char *const argv[] );
int execle(const char *pathname, const char *arg0, ... /* (char *)0, char *const envp[] */ );
int execve(const char *pathname, char *const argv[], char *const envp[] );
int execlp(const char *filename, const char *arg0, ... /* (char *)0 */ );
int execvp(const char *filename, char *const argv[] );
返回值:六个函数的返回值,若出错则返回-1,若成功则不返回值。
(二)苏格拉底挑战
1、知识点一
2、知识点二
二、问题与解决思路
(一)问题
在64位的乌班图系统中,无法直接使用gcc -m32 t.c ts.s指令进行32位的编译
type.h
ts.c
queue.c
t.c
(二)解决
三、实践过程
(一)exit函数:
(二)env
标签:char,第三章,文件,int,笔记,学习,进程,const,执行 From: https://www.cnblogs.com/20211125mjz/p/17779591.html