回忆昨天内容
一、获取文件的元数据(文件的类型 权限)
使用一些宏
或者位操作
二、文件夹的操作
文件夹的权限
opendir(3) closedir(3)readdir(3)
ls
三、文件锁
读锁 写锁
建议锁
fcntl(2)
可变参数
四、库函数和系统调用的关系
fopen(3) fclose(3) fgetc(3) fputc(3)
open(2) close(2) read(2) write(2)
五、文件操作的杂项
今天内容:
一、进程的基本知识
程序和进程
进程是资源分配的基本单位,进程有自己的pid PCB、
用户进程 树状形式组织的
pstree
进程间的关系 父子关系 兄弟关系
树根是一号进程 init进程
查看进程的信息 ps -aux
实时监控进程 top
二、创建新的进程
fork(2)
创建的进程会是进程树的一部分。
#include <unistd.h>
pid_t fork(void);
功能:创建一个子进程
参数:
返回值:成功 在父进程里返回子进程的pid ,在子进程里返回0
失败 父进程中返回-1 errno被设置
day07$a.out
parent process...
child process...
子进程 父进程
新建的进程是子进程 调用fork的进程是父进程
三、进程的终止
1 、return 和exit(3)的区别
函数中使用return代表从函数中返回而已,并不代表进程的终止
exit(3)这个函数一旦被调用,进程就结束了
#include <stdlib.h>
void exit(int status);
功能:使正常进程终止
参数:the value of status & 0377 is returned to the parent (see wait(2)).
返回值:无
0377 (八进制)->011111111 与其与运算后,保留低八位 0-255
原码 反码 补码
-1 以补码形式存放,负数的补码是负数的绝对值的原码按位取反+1
正数的补码是正数的原码本身
代码参见 exit.c
2、遗言函数
什么是遗言函数?
进程终止的时候调用的函数就是遗言函数
立遗言 在活着的时候
向进程注册遗言函数
atexit(3) on_exit(3)
#include <stdlib.h>
int atexit(void (*function)(void));
功能:注册一个函数在进程终止的时候被调用
参数:
function 遗言函数的名字 也就是遗言函数的入口地址
返回值:
注意:注册顺序和调用顺序相反
注册一次调用一次
子进程继承父进程的遗言函数
举例说明 atexit.c
#include <stdlib.h>
int on_exit(void (*function)(int , void *), void *arg);
功能:注册一个函数在进程终止的时候被调用
参数:
function 指定遗言函数,就是将这个函数注册给进程,作为进程的遗言函数
arg 传递给遗言函数的第二参数
返回值:成功0
错误 非0
void (*function)(int , void *)
举例说明 on_exit.c 向进程注册遗言函数
一个进程的父进程先他而去,将这个进程的父进程设置为init进程,这个进程就是孤儿进程
演示孤儿进程 代码参见 orphan.c
四、回收进程的资源
进程终止以后,将进程占用的资源回收回来
wait(2)家族的函数
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);
功能:挂起执行,等待子进程的终止
参数:
status 将子进程的退出状态保存在这个变量指向的空间里
可以使用以下宏检测子进程的退出状态和原因
WIFEXITED(status) 子进程正常终止,返回真
WEXITSTATUS(status) 必须在上个宏返回真的情况下,可以使用这个宏,获取子进程的退出状态吗,与了0377
WIFSIGNALED(status) 如果子进程被信号终止,返回真
WTERMSIG(status) 必须在上个宏返回真的情况下,才可以使用和这个宏,获取终止子进程的信号的编号
返回值:成功返回子进程的pid
错误 -1 设置errno
如何给指定进程发送指定信号?
kill -信号编号 进程的pid
代码参见 wait.c
僵尸进程 zombie
子进程终止了,但是父进程没有使用wait回收子进程的资源,这时候子进程是僵尸进程
代码参见 zombie.c
0 1 2
标准输入 标准输出 标准错误输出
pid_t waitpid(pid_t pid, int *status, int options);
atexit.c
#include<stdlib.h>
#include<t_stdio.h>
#include<t_file.h>
void bye(void)
{
printf("bye .....\n");
return;
}
void goodbye(void){
printf("good bye...\n");
return;
}
int main(){
atexit(bye);
atexit(bye);
atexit(goodbye);
pid_t pid=fork();
if(pid==-1){
E_MSG("fork",-1);
}
if(pid==0){
printf("this is son:\n");
}else{
sleep(1);
}
//getchar();
return 0;
}
exit.c
#include<stdlib.h>
#include<t_stdio.h>
int main()
{
exit(-1);
}
fork.c
#include<t_stdio.h>
#include<t_file.h>
int main(void){
//创建子进程
pid_t pid=fork();
if(pid==-1)
E_MSG("fork",-1);
if(pid==0){
printf("child process...%d\n",getpid());
printf("parent process in child...%d\n",getppid());
}else{
printf("parent process...%d\n",getpid());
printf("parent process in parent...%d\n",getppid());
}
return 0;
}
on_exit.c
#include<stdlib.h>
#include<t_stdio.h>
#include<t_file.h>
void bye(int n,void *v)
{
printf("n=%d\t %s\n",n,(char *)v);
return;
}
void goodbye(void){
printf("good bye...\n");
return;
}
int main(){
/* atexit(bye);
atexit(bye);
atexit(goodbye);
pid_t pid=fork();
if(pid==-1){
E_MSG("fork",-1);
}
if(pid==0){
printf("this is son:\n");
}else{
sleep(1);
}
*/
on_exit(bye,"good bye");
getchar();
return -1;
}
orphan.c
#include<t_stdio.h>
#include<t_file.h>
int main(void){
//创建子进程
pid_t pid=fork();
if(pid==-1) E_MSG("fork",-1);
if(pid==0){
printf("before parent dead pid:%d\n",getppid());
sleep(3);
printf("after parent dead pid:%d\n",getppid());
}else{
printf(" parent pid:%d\n",getppid());
sleep(1);
}
return 0;
}
wait.c
#include<t_stdio.h>
#include<sys/wait.h>
#include<stdlib.h>
#include<t_file.h>
int main(){
//创建 子进程
int s;
pid_t pid=fork();
if(pid==-1)E_MSG("fork",-1);
if(pid==0){//子进程执行的
printf("child process...%d\n",getpid());
getchar();
exit(-1);
}
else {
//父进程执行的
wait(&s);//挂起执行,等待子进程终止
printf("parent process...\n");
if(WIFEXITED(s))//子进程正常终止
//输出子进程终止状态码
printf("exit code:%d\n",WEXITSTATUS(s));
if(WIFSIGNALED(s))//子进程被信号打断
//输出打断子进程的信号编号
printf("signum...%d\n",WTERMSIG(s));
}
return 0;
}
zombie.c
#include<t_stdio.h>
#include<sys/wait.h>
#include<stdlib.h>
#include<t_file.h>
int main(){
//创建 子进程
int s;
pid_t pid=fork();
if(pid==-1)E_MSG("fork",-1);
if(pid==0){//子进程执行的
printf("child process...%d\n",getpid());
// getchar();
exit(-1);
}
else {
//父进程执行的
getchar();
wait(&s);//挂起执行,等待子进程终止
printf("parent process...\n");
if(WIFEXITED(s))//子进程正常终止
//输出子进程终止状态码
printf("exit code:%d\n",WEXITSTATUS(s));
if(WIFSIGNALED(s))//子进程被信号打断
//输出打断子进程的信号编号
printf("signum...%d\n",WTERMSIG(s));
}
return 0;
}