Ubuntu下UnixC的第七天

回忆昨天内容
一、获取文件的元数据(文件的类型 权限)
    使用一些宏
    或者位操作
二、文件夹的操作
    文件夹的权限
    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;
}
 


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值