进程的创建与终止

进程:正在执行的程序
命令ps查看进程,pstree查看所有进程
命令top相当于任务管理器,动态变化进程的信息

父子孤尸:
父子进程:父进程可以有多个子进程,一个子进程只能有一个父进程
调度进程:PID =0

孤儿进程:父进程先于子进程结束(一种状态),(老版本)操作系统会为子进程找父进程,即
被init进程收养,init进程又被称为孤儿院进程,(新版本)随机进程收养

僵尸进程:父子进程同时执行,子进程先于父进程结束,子进程还有部分资源在
内存中占用,父进程负责释放,但由于某种原因,父进程并没有回收子进程的终止状态,这时子进程处于僵尸
状态,被称为僵尸进程

进程标识:
当前进程:PID
当前进程父进程:PPID

1.实际用户id(real user id):当前进程的实际调用用户的id
2.有效用户id(effective user id):文件的set_user_id位被关闭,和实际用户id一样;
   set_uesr_id开启,为文件拥有者的id,
3.保存的设置用户id(saved set-user-id):程序运行时有效用户id的副本

//各种ID
#include<stdio.h>
#include<unistd.h>
int main(void)
{
    printf("  当前进程ID:%d\n",getpid());
    printf("    父进程ID:%d\n",getppid());
    printf("  实际用户ID:%d\n",getuid());
    printf("    用户组ID:%d\n",getgid());
    printf("  有效用户ID:%d\n",geteuid());
    printf("有效用户组ID:%d\n",getegid());
}

tarena: 
当前进程ID:88304
父进程ID:76181
实际用户ID:1000
用户组ID:1000
有效用户ID:1000
有效用户组ID:1000

root:su root 命令进入root用户,在root用户编译文件idroot执行
当前进程ID:88339
父进程ID:88321
实际用户ID:0
用户组ID:0
有效用户ID:0
有效用户组ID:0

当设置用户ID:在tarena用户编译
当前进程ID:88375
父进程ID:88343
实际用户ID:1000
用户组ID:1000
有效用户ID:0
有效用户组ID:1000

进程的创建:
fork();
一次创建,两次返回:返回值为子进程的PID和0;

子进程是父进程的不完全副本,除了会复制父进程的数据区、BSS区
、堆区、栈区、参数和环境变量外,包括输入输出缓冲区(内容也会)也会进行复制。
(代码区共享)

fork()函数返回后,系统内核会将父进程维护的文件描述符表也复制到
子进程的进程表项中,但并不复制文件表象。
父进程和子进程共哟个一个文件表象,子进程改变读写位置,父进程也随着改变

setbuf(setout,NULL);//关闭输出缓冲区

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
int global = 10;
int main(void)
{
    int local = 20;
    int * heap = (int*)malloc(sizeof(int));
    *heap =30;
    printf("进程:%d %p:%d %p:%d %p:%d\n",getpid(),&global,global,&local,local,heap,*heap);
    pid_t pid = fork();
    if(pid == -1)
    {
        perror("fork");
        return -1;
    }
    //子进程
    if(pid == 0)
    {
        printf("进程:%d %p:%d %p:%d %p:%d\n",getpid(),&global,++global,&local,++local,heap,++*heap);
        return 0;
    }
    //父进程
    sleep(1);
    printf("进程:%d %p:%d %p:%d %p:%d\n",getpid(),&global,global,&local,local,heap,*heap);
    return 0;
}


进程:90412 0x601068:10 0x7ffd2f3b0528:20 0xe66010:30
进程:90413 0x601068:11 0x7ffd2f3b0528:21 0xe66010:31
进程:90412 0x601068:10 0x7ffd2f3b0528:20 0xe66010:30

//子进程复制父进程的文件描述符表
#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
#include<string.h>

int main()
{
    //父进程打开文件
    int fd = open("./shared.txt",O_WRONLY | O_CREAT | O_TRUNC,0777);
    if(fd == -1)
    {
        perror("open");
        return -1;
    }
    //父进程写入hello word
    char * a ="hello world!";
    if(write(fd,a,strlen(a)) == -1)
    {
        perror("write");
        return -1;
    }
    //进入子进程
    pid_t pid = fork();
    if(pid == -1)
    {
        perror("fork");
        return -1;
    }
    //子进程改变文件读写位置
    if(pid == 0)
    {
        if(lseek(fd,-6,SEEK_END) ==-1)
        {
            perror("lseek");
            return -1;
        }
        close(fd);
            return 0;
    }
    //父进程写入linux
    sleep(1);
    char* b ="linux";
    if(write(fd,b,strlen(b)) == -1)
    {
        perror("write");
        return -1;
    }
    close(fd);
    return 0;
}

睡眠一秒钟文件内容为hello linux!

进程的终止:正常终止
1、从main函数中返回可令进程终止 return 0;
2、调用exit函数令进程终止 exit(0);//不返回

终止进程前做的事:
A、调用实现通过atexit或on_exit函数注册的退出处理函数; 
B、冲刷并关闭所有仍处于打开状态的标准I/O流; 
C、删除所有通过tmpfile函数创建的临时文件;
D、_exit(status);


3、调用_exit/EXIT令进程终止

终止进程前做的事:
A、关闭所有仍处于打开状态的文件描述符
B、将调用进程的所有子进程托付给init进程收养 
C、向调用进程的父进程发送SIGCHLD(17)信号
D、令调用进程终止运行,将status的低八位作为退出码保存在其终止状态中
 

异常终止:
1、当进程执行了某些在系统看起来具有危险性的操作,或系统本身发生了
某种故障或意外,内核会向相关进程发送特定的信号,如果进程无意针对
收到的信号采取补救措施,那么内核将按照缺省方式将进程杀死并视情节
生成和核心转储文件(core)以备事后分析,俗称吐核
SIGILL(4):进程试图执行非法指令
SIGBUS(7):硬件或对齐错误
SIGFPE(8):浮点异常
SIGSEG(11):无效内存访问
SIGPWR(30):系统供电不足
2、人为触发信号
SIGINT(2):Ctrl+C
SIGQUIT(3):Ctrl+\
SIGKILL(9):不能被捕获或忽略的进程终止信号
SIGTERM(15):可以被捕获或忽略的进程终止信号
3、向进程自己发送信号
#include<stdlib.h>
void abort(void);
功能:向调用进程发送SIGABRT(6)信号,该信号默认情况下可使进程
结束,无参数,不返回!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值