什么是进程?C语言

进程的概念

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

进程的内存分配

进程的作用

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

进程的状态

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

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

进程基本的函数

cs 复制代码
#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 会关闭所有的已经打开的文件,不执行清理函数。

  1. 主线程退出

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、创建两个线程:

cs 复制代码
#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、对父子进程共用代码端的观察

cs 复制代码
#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

cs 复制代码
 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:

cs 复制代码
#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

相关推荐
傻啦嘿哟42 分钟前
Python正则表达式:用“模式密码“解锁复杂字符串
linux·数据库·mysql
浪裡遊2 小时前
Linux常用指令
linux·运维·服务器·chrome·功能测试
SugarPPig3 小时前
PowerShell 查询及刷新环境变量
服务器
段ヤシ.3 小时前
银河麒麟(内核CentOS8)安装rbenv、ruby2.6.5和rails5.2.6
linux·centos·银河麒麟·rbenv·ruby2.6.5·rails 5.2.6
深夜情感老师5 小时前
centos离线安装ssh
linux·centos·ssh
我的作业错错错5 小时前
搭建私人网站
服务器·阿里云·私人网站
王景程5 小时前
如何测试短信接口
java·服务器·前端
微网兔子6 小时前
伺服器用什么语言开发呢?做什么用什么?
服务器·c++·后端·游戏
夸克App7 小时前
实现营销投放全流程自动化 超级汇川推出信息流智能投放产品“AI智投“
运维·人工智能·自动化
Rainbond云原生7 小时前
83k Star!n8n 让 AI 驱动的工作流自动化触手可及
运维·人工智能·自动化