Linux 文件操作编程是使用 UNIX/LINUX 提供的ANSI标准函数接口为基准对文件进行操作。
文件类型:
基于文件指针的文件操作函数是ANSI标准函数库的一部分。
在早期的多机处理系统中, 并发执行程序的话(由于并发程序的速度不同与资源竞争导致了程序执行的间断性),存在数据计算结果的不可再现性,这样的程序失去了其意义。
后来呢为了使得程序能并发执行且有效地对并发程序进行控制与描述,引入了进程的概念。
进程是如何产生的?
在程序运行前, 操作系统会为之分配一个PCB(进程控制块:系统通过PCB对进程控制与描述), PCB与程序段和程序相关的数据一起构成了进程实体。
进程的实质就是进程实体的一次运行过程。
进程和程序本身的区别
程序是静态的,是保存在磁盘上的指令的有序集合,进程是一个动态的概念
它是一个运行着的程序,包括了进程的动态创建,调度和消亡的过程,是Linux的基本调度单位。
进程 process:是 os 的最小单元 ,os 会为每个进程分配大小为 4g 的虚拟内存空间,其中 1g 给内核空间, 3g 给用户空间{代码区 数据区 堆栈区}
操作系统和进程间的联系
Linux 内核通过一个被称为 进程描述符的 task_struct 结构体来管理进程,这个结构体包含一个进程所需的所有信息。
它定义在 \kernel\msm-4.4\include\linux\sched.h 文件中,
struct task_struct {
进程描述信息
进程标识符
进程的用户标识符
进程控制信息
1.进程状态 2. 优先级
文件和文件系统
内存管理
信号处理
}
通过 标准 c 的函数可以获取当前进程的 pid 和 ppid
进程的用户ID 和 组ID
进程的有效用户ID 和 有效用户组ID
内核对进程用户执行的ID 进行检查时,检查的是其有效用户ID 和 有效用户组ID,默认情况下与真实用户ID 和 真实组ID 其是相等的
使用 geteuid 和 getegid 能得到进程的有效用户ID 和 有效用户组ID
chmod u+s myfife:为用户设置s权限,具有文件所有者的权限
chmod g+s Code:为用户组设置s权限,具有用户组的权限,可以对该目录下的文件执行权利,Code为目录
chmod o+t myfife:为其他用户设置t权限,说明其他用户不能对其进行删除操作
Linux 是多进程的系统,
进程间有并行性和互不干扰性,进程间是各自分离的任务,每个进程拥有各自的权力和责任。
每个进程都运行在各自独立的虚拟地址空间,因此,即使一个进程发生了异常,它也不会影响到系统的其他进程。
1. ps -elf 查看系统中的进程。ps 命令是一个采样的信息。
2. ps -aux 可以查看进程的CPU和内存的占用率。
3. echo $$打印当前bash的进程ID。
4. top命令 动态的显示进程的信息,
展示的是系统中CPU占用率最高的20个进程。
5. kill命令,给进程发信号,
使用方式:kill -信号的编号 进程ID。通过kill -l可以查看所有信号。
6. nice命令按照指定的优先级运行进程,
renice命令可以修改进程的nice值,nice值的范围:-20-19。
1. nice -n 可执行程序
2. renice -n 指定的nice值 -p 进程ID
先来先服务调度算法FCFS:队列实现,非抢占,先请求CPU的进程先分配到CPU,可以作为作业调度算法也可以作为进程调度算法;按作业或者进程到达的先后顺序依次调度,对于长作业比较有利;
优先级调度算法(可以是抢占的,也可以是非抢占的):优先级越高越先分配到CPU,相同优先级先到先服务,存在的主要问题是:低优先级进程无穷等待CPU,会导致无穷阻塞或饥饿;
时间片轮转调度算法(可抢占的):按到达的先后对进程放入队列中,然后给队首进程分配CPU时间片,时间片用完之后计时器发出中断,暂停当前进程并将其放到队列尾部,循环 ;队列中没有进程被分配超过一个时间片的CPU时间,除非它是唯一可运行的进程。如果进程的CPU区间超过了一个时间片,那么该进程就被抢占并放回就绪队列。
最短作业优先调度算法SJF:作业调度算法,算法从就绪队列中选择估计时间最短的作业进行处理,直到得出结果或者无法继续执行,平均等待时间最短,但难以知道下一个CPU区间长度;缺点:不利于长作业;未考虑作业的重要性;运行时间是预估的,并不靠谱 ;
高相应比算法HRN:响应比=(等待时间+要求服务时间)/要求服务时间;
多级队列调度算法:将就绪队列分成多个独立的队列,每个队列都有自己的调度算法,队列之间采用固定优先级抢占调度。其中,一个进程根据自身属性被永久地分配到一个队列中。
多级反馈队列调度算法:目前公认较好的调度算法;设置多个就绪队列并为每个队列设置不同的优先级,第一个队列优先级最高,其余依次递减。优先级越高的队列分配的时间片越短,进程到达之后按FCFS放入第一个队列,如果调度执行后没有完成,那么放到第二个队列尾部等待调度,如果第二次调度仍然没有完成,放入第三队列尾部…。只有当前一个队列为空的时候才会去调度下一个队列的进程。与多级队列调度算法相比,其允许进程在队列之间移动:若进程使用过多CPU时间,那么它会被转移到更低的优先级队列;在较低优先级队列等待时间过长的进程会被转移到更高优先级队列,以防止饥饿发生。
1. 会话,控制终端,会话中的首进程是bash进程,一个会话下面可以有多个进程组。包括一个前台进程组和若干个后台进程组。
2. 前台进程组,可以接受控制终端上传输的数据。
3. 后台运行一个进程,在执行程序时后面加一个&符号,变成了后台进程。,
后台进程在会话结束后会自动结束。
4. 通过jobs命令可以看到当前会话下面的后台作业,每个作业都有一个编号。可以通过fg+作业编号把后台运行的作业拉回到前台。拉回到前台之后,就可以通过控制终端跟前台进程交互。
#include
pid_t fork(void);
在Linux 中 fork 函数实现了创建一个新进程的效果:
fork 函数创建子进程的过程为:
写时复制的技术(Cow)
父子进程的堆栈内存变量在双方都不进行修改的情况下是指向同一虚拟地址的,也可以说目前变量归父子进程共享, 仅在修改时才会产生新的地址。
int execl(const char *path, const char *arg, ...)
使用 add.exe 直接覆盖掉当前进程
execl(“./add.exe” ,”add.exe” ,”3” , “4” , NULL):
exec 的工作原理与 fork 完全不同, fork 是在复制一份原进程,而 exec 函数是用 exec 的第一个参数指定的程序覆盖现有进程空间(也就是说执行 exec 族函数之后,它后面的所有代码不在执行)。
我们输入的 bash命令可以这样理解:
bash父进程 -> fork 分割出子进程 ,
execl 将子进程转到命令为(例如ls)的进程
#include
int system(const char *string);
system 函数通过调用 shell 程序/bin/sh –c 来执行 string 所指定的命令,该函数在内部是通过调用execve(“/bin/sh”,…)函数来实现的。
通过 system 创建子进程后,原进程和子进程各自运行,相互间关联较少。如果 system 调用成功,将返回 0。
system函数的参数还可以是一个可执行程序,例如:
system(“/home/wangxiao/1”);如果想要执行system后面进程的时候,不至于对当前进程进行阻塞,可以利用&将/home/wangxiao/1调到后台运行。
进程的终止:
进程的终止有 5 种方式:
⚫ main 函数的自然返回;
⚫ 调用 exit 函数
⚫ 调用_exit 函数
⚫ 调用 abort 函数
⚫ 接收到能导致进程终止的信号 ctrl+c SIGINT ctrl+\ SIGQUIT
exit() 与 _exit() 的区别:
进程的控制
孤儿进程:
用 fork 函数启动一个子进程时,子进程就有了它自己的生命并将独立运行。
如果父进程先于子进程退出,则子进程成为孤儿进程,此时将自动被 PID 为 1 的进程
(即 init)接管。孤儿进程退出后,它的清理工作有祖先进程 init 自动处理。但在 init 进程,清理子进程之前,它一直消耗系统的资源,所以要尽量避免。
僵尸进程:
如果子进程先退出,系统不会自动清理掉子进程的环境,而必须由父进程调用 wait 或 waitpid 函数来完成清理工作,如果父进程不做清理工作,则已经退出的子进程将成为僵尸进程(defunct),在系统中如果存在的僵尸(zombie)进程过多,将会影响系统的性能,所以必须对僵尸进程进行处理。
#include
#include
pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);
wait 和 waitpid 都将暂停父进程,等待一个已经退出的子进程,并进行清理工作;
wait 函数随机地等待一个已经退出的子进程,并返回该子进程的 pid;
waitpid 等待指定 pid 的子进程;如果为-1 表示等待所有子进程。
status 参数是传出参数,存放子进程的退出状态;通常用下面的两个宏来获取状态信息:
WIFEXITED(status) 如果子进程正常结束,它就取一个非 0 值。传入整型值,
非地址
WEXITSTATUS(status) 如果 WIFEXITED 非零,它返回子进程的退出码,在bash进程下使用
echo $? 能获取上一次等待的进程的退出码。
options 用于改变 waitpid 的行为,其中最常用的是 WNOHANG,它表示无论子进程是
否退出都将立即返回,不会将调用者的执行挂起