什么是进程?C语言

进程的概念

进程就是执行中的程序,是系统资源分配的最小单位。

进程的内存分配

进程的作用

宏观上是并行的,微观上是串行的

进程的状态

对于基本的操作系统:有三个状态: 就绪态->执行态-> 阻塞态

在LInux中有四种:运行态,睡眠态,僵尸态,暂停态。

进程基本的函数

#include <unistd.h>             //fork()函数的头文件

fork( )

一次调用,会返回两次。
子进程先运行和是父进程先进程,顺序不确定。
变量不共享。
子进程复制父进程的0到3g空间和父进程内核中的PCB,但id号不同。(同非常ID号子比父的要大一些)
功能:通过该函数可以从当前进程中克隆一个同名新进程。
          克隆的进程称为子进程,原有的进程称为 父进程。
          子进程是父进程的完全拷贝。
          子进程的执行过程是从fork函数之后执行。

返回值:
int 类型的数字
在父进程中 : 成功   返回值是子进程的pid号 > 0
            失败   返回-1
在子进程中: 成功    返回值0
               失败   无


getpid()

获得本进程的pid号

getppid()

获得父进程的pid号

父子进程的关系

子进程是父进程的副本。子进程获得父进程数据段,堆,栈,正文段共享。

进程的终止

8个情况
1)main 中return
2)exit(), c库函数,会执行io库的清理工作,关闭所有 的流,以及所有打开的文件。已经清理函数(atexit)。
3)_exit,_Exit 会关闭所有的已经打开的文件,不执行清理函数。
4) 主线程退出
5)主线程调用pthread_exit

异常终止
6)abort()
7)signal   kill pid
8)最后一个线程被pthread_cancle
 

注意:

exit(0  /  1 )  在使用的时候都是对的写 0 
                        存在错误的时候写            1

僵尸进程和孤儿进程

僵尸进程:一个主进程用fork创建了子线程,当子线程结束的时候,主线程没有调用wait或者waitpid回收掉这个子进程,这个子进程的任务描述符仍然在系统中。

孤儿进程:一个主进程用fork创建了子线程,主进程已经退出了,而子进程还在继续运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。

进程操作示例代码:

1、创建两个线程:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
 #include <sys/types.h>

int main(int argc, char *argv[])
{
    pid_t pid = fork();               //用pid接受fork的返回值判断是父进程还是子进程
    if(pid>0)
    {
        while(1)
        {
            printf("fahter, 发送视频\n");
            sleep(1);
        }
    }
    else if(0 == pid)
    {
    
        while(1)
        {
            printf("child, 接收控制\n");
            sleep(1);
        }
    }
    else 
    {
        perror("fork");
        return 1;
    }
    
    return 0;
}

2、对父子进程共用代码端的观察

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
int a = 10;
int main(int argc, char *argv[])
{
    pid_t pid = fork();
    if(pid>0)
    {
        sleep(3);
        printf("father  a is %d\n",a);
    }
    else if(0 == pid)
    {
        a+=20;
        printf("child  a is %d\n",a);
    }
    else 
    {
        perror("fork");
        return 1;
    }
    
    printf("a is %d\n",a);
    return 0;
}


//输出结果
child a is 30 
a is 30
father a is 10
a is 10

由此可知在父子进程中,在fork之前部分的代码为共用,而分进程之后进行的操作各自都会有自己的执行空间。

3、获得自己的pid和父进程的pid

 pid_t pid = fork();
    if(pid>0)
    {
        sleep(3);
        printf("father  a is %d, pid:%d ppid:%d\n",a,getpid(),getppid());
    }
    else if(0 == pid)
    {
        a+=20;
        printf("child  a is %d pid:%d ,ppid:%d\n",a,getpid(),getppid());
    }
    else 
    {
        perror("fork");
        return 1;
    }

4、atexit //注册终止函数

调用了exit函数使进程终止退出,在进程终止之前,如果注册了终止函数,那么exit函数会先去依次调用进程终止函数,,每调用完一个终止函数并返回,调用顺序是以栈的形式来调用,调用flush刷新IO缓冲区的数据之后返回。

eg:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
char * tmp=NULL;
void clean(void)
{
    printf("this is clean %s\n",tmp);
    free(tmp);
}
int main(int argc, char *argv[])
{
    atexit(clean);
    tmp =(char*) malloc(50);
    strcpy(tmp,"hello");

    printf("123123\n");


    return 0;
}

输出结果为:

123123

this is clean  hello 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值