回顾:
文件相关 - 文件锁、文件相关函数
目录相关函数 - 4个+2个读目录的函数
文件锁主要是 读写锁,正确用法是 在调用读函数之前加读锁,在调用写函数之前加写锁,使用完毕后释放锁。如果需要一直等待加锁,可以F_SETLKW实现。
文件相关函数 - stat() access() chmod() truncate() ...
mmap和fd结合使用,让虚拟内存地址映射文件。mmap和open的权限 保持一致,一般都是 读写权限。
目录相关函数 - mkdir() rmdir() chdir() getcwd()
读目录子项的函数 - opendir() readdir()
今天:
目录的收尾
进程的概念
进程的相关函数 - fork()
wait() waitpid()
进程 - 一个在内存中运行的程序
主流的操作系统基本都支持 多进程。
Linux中查看进程的方法
ps - 查看本终端启动的进程
ps -aux Linux专用的查看进程
ps -ef Unix/Linux通用的查看进程
显示的东西有所差别,Unix系统不直接支持ps -aux
但/usr/ucb/ps -aux 可以执行。
kill -9 进程ID 可以杀进程。
如果进程a启动了进程b,a叫父进程,b叫子进程。
Unix/Linux的进程启动次序,首先内核启动0进程,0进程 启动 1进程和2进程(有些Linux只启动1进程),1进程 和 2进程 再 启动其他所有进程。
进程的常见状态:
S - 休眠状态(省资源)
s - 有子进程
O - 可运行状态
R - 运行状态
Z - 僵尸进程(已经结束但资源没有回收的进程)
父子进程之间的关系:
1 父进程启动子进程后,父子进程同时运行。
2 如果子进程先结束,子进程会给父进程发信号,由父进程负责回收子进程的相关资源。
3 如果父进程先结束,子进程变成孤儿进程,孤儿进程会把init进程(进程1)作为新的父进程,init进程也叫孤儿院。
4 如果子进程先结束,同时发的信号父进程没有收到或者子进程没有发信号,子进程就变成僵尸进程。
关于进程的ID - PID
进程ID在同一时刻 确保唯一,但支持 延迟重用。
取进程ID的函数:
getpid() - 取当前进程id
getppid() - 取当前进程的父进程的PID
getuid() geteuid() - 取有效用户的ID
创建新的子进程函数 - fork()/vfork()
pid_t fork(void); - 非常简单但非常复杂的函数
fork()是通过复制自身(父进程)创建子进程。
fork()创建的子进程,会复制父进程除代码区之外的内存区域,但 和父进程共享代码区。
fork()之前的代码 父进程执行一次,fork()之后的代码父子进程分别执行一次。fork()函数会有两次返回,父进程返回 子进程ID,子进程返回0。因此可以用fork()返回值区分父子进程。返回 -1 代表失败。
if(pid == 0){
//子进程
}else{
//父进程
}
fork()之后,父子进程同时运行,但谁先运行,谁先结束都 不确定。不同的操作系统对于 谁先运行算法不同。
fork() 子进程复制父进程的内存区域(代码区除外)的过程:子进程和父进程变量地址一样,但对应的物理内存不一样,子进程会复制父进程内存中的数据。fork()结束之后,父子进程在内存区域中的数据没有任何的关系。
fork()如果复制文件描述符时,只复制描述符,不复制文件表。
fork()创建子进程之后,父子进程代码可以同时执行(并行)。
练习:模拟聊天室
启动10个子进程,每个子进程休眠1秒,然后打印进程xxx退出了聊天室。 xxx就是子进程的id。然后子进程就结束了。
效果是 10个子进程同时结束。
注意:子进程一定要写exit()
ps -aux 查看一下是否有没有杀掉的子进程
kill -9 进程ID 杀进程
进程结束的方式:
正常结束:
main()执行了return
执行了exit()/_exit()/_Exit()
最后一个线程结束
非正常结束:
信号
被其他线程取消了最后一个线程
exit()/_exit()/_Exit()的区别:
1 _exit()和_Exit()本质上是一样的,区别只是前者是uc函数,后者是标C函数。
2 exit() 和 _Exit()区别是 exit()并不是立即退出,在退出前会调用某些函数,只要函数用atexit(函数指针)注册,退出前就会被调用。_Exit()是立即退出,不会做任何额外的事情。
大多数情况下,退出 调用 exit(int) 即可。
进程之间的调度(如何让父进程等待子进程)
wait() waitpid()就是进程之间的调度函数
pid_t wait(int* status)
用于 父进程等待子进程的结束,如果父进程有多个子进程的话,等待任意一个子进程结束都会返回。wait的返回值pid_t 可以获取结束子进程的PID,参数status用于 返回结束子进程的状态和退出码。
wait()可以回收僵尸子进程。
宏函数 WIFEXITED(status)可以判定是否正常结束
宏函数 WEXITSTATUS取退出码(exit(退出码))
(退出码后8位有效)
作业:
1 文件/目录函数,做myls,实现ls -l的功能。
目录的处理方式和文件处理方式不同。
2 理解fork()和wait()
s,实现ls -l的功能。
目录的处理方式和文件处理方式不同。
2 理解fork()和wait()