Linux--进程控制_linux int p=null,GitHub标星3.2K

这篇具有很好参考价值的文章主要介绍了Linux--进程控制_linux int p=null,GitHub标星3.2K。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新大数据全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
Linux--进程控制_linux int p=null,GitHub标星3.2K,2024年程序员学习,linux,github,运维
Linux--进程控制_linux int p=null,GitHub标星3.2K,2024年程序员学习,linux,github,运维
Linux--进程控制_linux int p=null,GitHub标星3.2K,2024年程序员学习,linux,github,运维
Linux--进程控制_linux int p=null,GitHub标星3.2K,2024年程序员学习,linux,github,运维
Linux--进程控制_linux int p=null,GitHub标星3.2K,2024年程序员学习,linux,github,运维

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip204888 (备注大数据)
Linux--进程控制_linux int p=null,GitHub标星3.2K,2024年程序员学习,linux,github,运维

正文

写时拷贝

**当父子代码只读时,父子的代码和数据是共享的。但是任意一方试图写入时,便以写时拷贝的方式各自一份副本。**具体见下图:

Linux--进程控制_linux int p=null,GitHub标星3.2K,2024年程序员学习,linux,github,运维

我们发现最开始父子进程都是指向的同一物理内存,但是当发生写入时。我们发现通过写时拷贝,子进程重新指向一块物理内存。

fork调用失败的原因

关于fork调用失败的两个原因

1.系统中有太多的进程

2.实际用户的进程数超过了限制

这段代码是测试你的用户能跑好多个进程,但是不建议跑。因为跑了之后就会影响bash,会导致系统出错!代码如下:

#include <stdio.h>
#include <unistd.h>

int main()
{
    int cnt = 0;
    while(1)
    {
        int ret = fork();
        if(ret < 0){
            printf("fork error!, cnt: %d\n", cnt);
            break;
        }
        else if(ret == 0){
            //child
            while(1) sleep(1);
        }
        //partent
        cnt++;
    }
    return 0;
}

当运行后就会出现如下错误:

-bash: fork: retry: No child processes
-bash: fork: retry: No child processes
-bash: fork: retry: No child processes
-bash: fork: retry: No child processes
-bash: fork: Resource temporarily unavailable
-bash-4.2$

解决方法:

1.kill -9 -1 //将进程全部杀死

2.重新增加一个用户使用

进程终止


进程退出场景

代码运行完毕,结果正确 --return 0;

代码运行完毕,结果不正确 --return !0;退出码

代码异常终止 --退出码无意义

进程常见退出方法

正常终止(可以通过 echo $? 查看进程退出码)

  1. 从main返回–return 返回

  2. 调用exit --任意地方调用

  3. _exit

异常退出:

ctrl + c,信号终止

return退出

return是一种更常见的退出进程方法。执行return n等同于执行exit(n),因为调用main的运行时函数会将main的返回值当做 exit的参数。

我们通过return返回0为正确,返回其他为错误,代码如下:

#include <stdio.h>    
    
int addToTarget(int from, int to)    
{    
    
    int sum = 0;    
    int i=0;    
    for(i = from; i < to; i++)    
    {    
         sum += i;    
    }    
    return sum;    
}    
    
                                                                                                                                                                                           
int main()    
{    
    //进程退出的时候,对应的退出码    
    //标定进程执行结果是否正确    
    
    int num = addToTarget(1, 100);    
    if(num == 5050)    
        return 0;    
    else    
        return 1;    
    
    return 0;    
}

运行结果:

[hongxin@VM-8-2-centos 12-14]$ ./mytest 
[hongxin@VM-8-2-centos 12-14]$ echo ? 1 [ h o n g x i n @ V M − 8 − 2 − c e n t o s 12 − 14 ] ? 1 [hongxin@VM-8-2-centos 12-14] ?1[hongxin@VM82centos1214] echo $?
0

代码解释:

./mytest:运行一个进程

echo:显示

$?:永远记录最近的一个在命令行中执行完毕时对应的退出码(main->return ?:)

这里的1:标识错误,是mytest进程中代码不正确

这里的0:标识正确,因为echo $?本来都是一个进程

前面也说过退出码0标识成功,其他表示不正确,但是不同的数字可以描述不同错误,对于计算机来说很好识别数字,但对于程序员来说语言描述是更加友好。所以在学习c语言的时候,我们就学习过strerror,就是用字符串进行描述,它大概有134种标识;

运行代码:

for(int i=0;i<200;i++)
   {
         printf(“%d:%s\n”,i,strerror(i) );
    }

运行结果:

[hongxin@VM-8-2-centos 12-14]$ ./mytest 
0:Success

1:Operation not permitted
2:No such file or directory
3:No such process
4:Interrupted system call
5:Input/output error
6:No such device or address

127:Key has expired
128:Key has been revoked
129:Key was rejected by service
130:Owner died
131:State not recoverable
132:Operation not possible due to RF-kill
133:Memory page has hardware error
134:Unknown error 134

exit函数

#include <unistd.h>

void exit(int status);

参数:status 定义了进程的终止状态,父进程通过wait来获取该值

说明:虽然status是int,但是仅有低8位可以被父进程所用。所以_exit(-1)时,在终端执行$?发现返回值 是255。

当exit(-1)时,结果如下

运行结果:

[hongxin@VM-8-2-centos 12-14]$ ./mytest 
hello bit![hongxin@VM-8-2-centos 12-14]$ echo $?
255

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>

int addToTarget(int from, int to)
{    
    
    int sum = 0;    
    int i=0;    
    for(i = from; i < to; i++)    
    {    
         sum += i;    
    }    
//    return sum;    
    exit(12);                                                                                                                                                                              
}    
    
    
int main()    
{    
    
     printf("hello world!\n");    
     int ret = addToTarget(0, 100);    
     printf("sum=%d\n", ret);    
    
    while(1) sleep(1);    
}

[hongxin@VM-8-2-centos 12-14]$ ./mytest  
hello world!                                   //exit在调用addToTarget函数时直接退出

[hongxin@VM-8-2-centos 12-14]$ echo $?
12

_exit函数与exit函数

使用方法不变,exit是库函数,_exit系统调用。他们本质就是上下层关系。

实例:

int main()

{

printf(“hello”);

exit(0);

}

运行结果:

[root@localhost linux]# ./a.out

hello[root@localhost linux]#

//前面两秒没有数据,后两秒显示数据


int main()

{

printf(“hello”);

_exit(0);

}

运行结果:

[root@localhost linux]# ./a.out

[root@localhost linux]#

//前两秒没有数据,两秒后程序直接退出

**结论:**exit 终止进程,主动刷新缓冲区;_exit终止进程,不会刷新缓冲区

那么缓存区再哪儿呢?

我们发现如果缓冲区在操作系统层,不管是exit还是_eixt都会刷新缓冲区。实则是在用户级的缓存区,后面基础I/O会将。

exit最后也会调用exit, 但在调用exit之前,还做了其他工作:

  1. 执行用户通过 atexit或on_exit定义的清理函数。

  2. 关闭所有打开的流,所有的缓存数据均被写入

  3. 调用_exit

Linux--进程控制_linux int p=null,GitHub标星3.2K,2024年程序员学习,linux,github,运维

进程等待


进程等待必要性

之前讲过,子进程退出,父进程如果不管不顾,就可能造成‘僵尸进程’的问题,进而造成内存泄漏。

另外,进程一旦变成僵尸状态,那就刀枪不入,“杀人不眨眼”的kill -9 也无能为力,因为谁也没有办法 杀死一个已经死去的进程。

最后,父进程派给子进程的任务完成的如何,我们需要知道。如,子进程运行完成,结果对还是不对, 或者是否正常退出。

父进程通过进程等待的方式,回收子进程资源,获取子进程退出信息

进程等待的方法

wait方法

#include <sys/types.h>

#include <sys/wait.h>

pid_t wait(int*status);

返回值:

成功返回被等待进程pid,失败返回-1。

参数:

输出型参数,获取子进程退出状态,不关心则可以设置成为NULL

通过fork创建进程, 每次打印时睡眠1秒,观察这5秒的状态。等子进程结束后,睡眠10秒,观察该进程的状态,最后wiat等待后,父进程接受到子进程后的状态。

脚本:

while :; do  ps axj | head -1 && ps axj | grep mytest| grep -v grep ;sleep 1; done

#include <stdio.h>    
#include <unistd.h>    
#include <string.h>    
#include <stdlib.h>    
#include <sys/types.h>    
#include <sys/wait.h>    
    
int main()    
{    
    pid_t id = fork();    
    if(id == 0)    
    {    
        //子进程    
        int cnt = 5;    
        while(cnt)    
        {    
            printf("我是子进程: %d, 父进程: %d, cnt: %d\n", getpid(), getppid(), cnt--);            sleep(1);
        }                
        exit(0); //进程退出
    }                          
    sleep(10);                                                                             

    pid_t ret = wait(NULL);
    if(id > 0)                 
    {             
        printf("wait success: %d", ret);
    }                                       
         
    sleep(5);
} 

Linux--进程控制_linux int p=null,GitHub标星3.2K,2024年程序员学习,linux,github,运维

通过观察我们发现最开始为S状态–等待状态,子进程结束后未被父进程接受变成Z状态–僵尸状态,最后通过等待后返回子进程信息,子进程结束,父进程运行。

waitpid方法

pid_ t waitpid(pid_t pid, int *status, int options);

返回值:

当正常返回的时候waitpid返回收集到的子进程的进程ID;

如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0;

如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在;

参数:

pid:

Pid=-1,等待任一个子进程。与wait等效。

Pid>0.等待其进程ID与pid相等的子进程。

status:

WIFEXITED(status): 若为正常终止子进程返回的状态,则为真。(查看进程是否是正常退出)

WEXITSTATUS(status): 若WIFEXITED非零,提取子进程退出码。(查看进程的退出码)

options:

WNOHANG: 若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待。若正常结束,则返回该子进程的ID。

获取子进程status

wait和waitpid,都有一个status参数,该参数是一个输出型参数,由操作系统填充。

如果传递NULL,表示不关心子进程的退出状态信息。 否则,操作系统会根据该参数,将子进程的退出信息反馈给父进程。

status不能简单的当作整形来看待,可以当作位图来看待,具体细节如下图(只研究status低16比特位):

Linux--进程控制_linux int p=null,GitHub标星3.2K,2024年程序员学习,linux,github,运维

整数的低 16 位,其中又可以分为 最低八位 和 次低八位

其中重要的是:可以通过提取 status 的次低八位,就可以拿到子进程的退出码。

core dump–核心转储

*它是操作系统在进程收到某些信号而终止运行时,将此时进程地址空间的内容以及有关进程状态的其他信息写出的一个磁盘文件,这种信息往往用于调试。*后面在信号阶段的时候会详细介绍。

代码测试如下:

int main()    
{    
    pid_t id = fork();    
    if(id == 0)    
    {    
        //子进程    
        int cnt = 5;    
        while(cnt)    
        {    
            printf("我是子进程: %d, 父进程: %d, cnt: %d\n", getpid(), getppid(), cnt--);    
           int *p = NULL;    
            *p = 100;    
            sleep(1);    
        }    
        // 运行完    
        // 1. 代码完,结果对    
        // 2. 代码完,结果不对    
        // 异常    
        // 3. 代码没跑完,出异常了    
        exit(12); //进程退出    
       //`` exit(0); //进程退出    
    }       
                                                                                                                                                                                           
    int status = 0; // 不是被整体使用的,有自己的位图结构    
    pid_t ret = waitpid(id, &status, 0);    
    if(id > 0)                  
    {                           
        printf("wait success: %d, sig number: %d, child exit code: %d\n", ret, (status & 0x7F), (status>>8)&0xFF);    
    }                           
                                
    sleep(5);                   
} 

关于下面代码,我们知道status本质是位图,位图可以对指定区域进行访问,那么我们只需要取其次低八位。所以我们可以用 位操作来完成,将status 右移八位再按位与上 ,即 (status>>8)&0xFF ,就可以提取到 status的次低八位了。

printf(“wait success: %d, sig number: %d, child exit code: %d\n”, ret, (status & 0x7F), (status>>8)&0xFF);

该代码其目的就是为了让父进程获取到子进程的退出码,如下实验结果也是证实了在子进程中获取的pid,ppid与我们通过提取 status 的次低八位的结果一样。就证实了可以通过status 拿到进程的退出码。

运行结果:

[hongxin@VM-8-2-centos 12-15]$ ./mytest 
我是子进程: 6347, 父进程: 6346, cnt: 5
wait success: 6347, sig number: 11, child exit code: 0

Linux--进程控制_linux int p=null,GitHub标星3.2K,2024年程序员学习,linux,github,运维

通过kill手册可以明确地得到是野指针的问题!

阻塞与非阻塞

如果子进程已经退出,调用wait/waitpid时,wait/waitpid会立即返回,并且释放资源,获得子进程退出信息。

如果在任意时刻调用wait/waitpid,子进程存在且正常运行,则进程可能阻塞。

如果不存在该子进程,则立即出错返回。

Linux--进程控制_linux int p=null,GitHub标星3.2K,2024年程序员学习,linux,github,运维

用更直白的话就是:在子进程运行的时候,父进程一直处于等待状态,这个时候父进程一直检测子进程状态,这个时候父进程没有干其他事情,这个过程就叫做—阻塞。

相反的,如果在子进程运行的时候,父进程一直处于等待状态,这个时候父进程一直检测子进程状态,如果没有就绪,那么就直接返回,这个时候父进程能干一其他的事,这个过程就叫—非阻塞。每一次都是一次非阻塞等待;多次非阻塞等待就叫–轮询

那么非阻塞有什么好处呢!如果当父进程检查到子进程未就绪,那么父进程就可以做一些其他的任务。

非阻塞的好处就是:不会占用父进程的所有精力,可以在轮询期间,做其他任务。

非阻塞

代码测试:

#include <assert.h>

#define NUM 10

typedef void (*func_t)(); //函数指针

func_t handlerTask[NUM];

//样例任务
void task1()
{
    printf("handler task1\n");
}
void task2()
{
    printf("handler task1\n");
}
void task3()
{
    printf("handler task1\n");
}

void loadTask()
{
    memset(handlerTask, 0, sizeof(handlerTask));
    handlerTask[0] = task1;
    handlerTask[1] = task1;                                                                                                                                                                
    handlerTask[2] = task1;
}

void addtask()
{}
int main()
{
    pid_t id = fork();
    assert(id != -1);
    if(id == 0)
    {                                                                                                                                                                                      
        //child
        int cnt = 10;
        while(cnt)
        {
            printf("child running, pid: %d, ppid: %d, cnt: %d\n", getpid(), getppid(), cnt--);
            sleep(1);
        //    int *p = 0;
        //    *p = 100; //野指针问题
        }

        exit(10);
    }

    loadTask();
    // parent
    int status = 0;
    while(1)
    {
        pid_t ret = waitpid(id, &status, WNOHANG); //WNOHANG: 非阻塞-> 子进程没有退出, 父进程检测时候,立即返回
        if(ret == 0)
        {
            // waitpid调用成功 && 子进程没退出
            //子进程没有退出,我的waitpid没有等待失败,仅仅是监测到了子进程没退出.
            printf("wait done, but child is running...., parent running other things\n");
            for(int i = 0; handlerTask[i] != NULL; i++)
            {
                handlerTask[i](); //采用回调的方式,执行我们想让父进程在空闲的时候做的事情
            }
        }
        else if(ret > 0)
        {
            // 1.waitpid调用成功 && 子进程退出了
  printf("wait success, exit code: %d, sig: %d\n", (status>>8)&0xFF, status & 0x7F);
            break;
        }
        else
        {
            // waitpid调用失败
            printf("waitpid call failed\n");
        //    break;
        }
        sleep(1);
    }
    return 0;

}

运行结果:

[hongxin@VM-8-2-centos 12-16]$ make
gcc -o mychild mychild.c -std=c99
[hongxin@VM-8-2-centos 12-16]$ ./mychild 
wait done, but child is running…, parent running other things
handler task1
handler task1
handler task1
child running, pid: 22206, ppid: 22205, cnt: 10
wait done, but child is running…, parent running other things
handler task1
handler task1
handler task1

wait done, but child is running…, parent running other things
handler task1
handler task1
handler task1
wait done, but child is running…, parent running other things
handler task1
handler task1
handler task1
wait success, exit code: 10, sig: 0

进程程序替换


替换原理

用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),子进程往往要调用一种exec函数以执行另一个程序。当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行。调用exec并不创建新进程,所以调用exec前后该进程的id并未改变。

Linux--进程控制_linux int p=null,GitHub标星3.2K,2024年程序员学习,linux,github,运维

代码测试

#include <stdio.h>    
#include <stdlib.h>    
#include <sys/types.h>    
#include <sys/wait.h>    
#include <assert.h>    
#include <unistd.h>    
    
    
int main()    
{    
    printf("process is running..\n");    
    
    execl("/usr/bin/ls","ls","-a",NULL);                                                                                                                                                   
    
    
    printf("process is running..\n");    
    return 0;    
} 

测试结果:

[hongxin@VM-8-2-centos 12-16_1]$ ./myexec 
process is running…
.  …  Makefile  myexec  myexec.c

通过测试结果我们发现没有打印最后的printf,这个原因就是因为printf在execl之后,当execl执行完之后,代码和数据已经完全被覆盖,开始执行新的代码了,所以printf就无法执行了!

当我们写错后,又会是怎样的结果呢?

测试代码:

execl(“/usr/bin/djhalshl”,“ls”,“-a”,NULL);                                                                                   测试结果:

[hongxin@VM-8-2-centos 12-16_1]$ ./myexec 
process is running…
process is running…

因为我们输入时是错误的地址,检测不到,这个时候execl函数就会调用失败,那么代码和数据就没有被替换,下面代码就继续执行。

我们通过查man手册,我们又发现execl只有错误时返回值,而没有正确时的返回值。

RETURE VALUE
       The exec() functions return only if an error has occurred.  The return value is -1, and errno is set to indicate the error.

这是因为成功后代码和数据就被覆盖了,再对下面判断就毫无意义,只要返回就一定是错误!

通常写法

int main()    
{    
    printf("process is running..\n");    
                                                                                                                                                                                           
    pid_t id  = fork();    
    assert(id != -1);    
    
    if(id == 0)    
    {    
        execlp("ls", "ls", "-a", "-l", "--color=auto", NULL);    
         exit(1);    
    
    }    
    
    int status = 0;    
    pid_t ret = waitpid(id, &status, 0);    
    if(ret>0) printf("wait success: exit code: %d, sig: %d\n", (status>>8)&0xFF, status & 0x7F);    
    
    printf("process is running..\n");    
    return 0;    
}

为了使execl不影响父进程的代码和数据,让子进程来执行来执行父进程的一部分代码。因为虚拟地址空间加页表保证了进程的独立性,一旦有执行流想要替换代码和数据,就会发生写时拷贝。

运行结果:

wait success: exit code: 0, sig: 0
process is running…

总结:创建子进程就是想让子进程执行一个全新的程序

替换函数

#include <unistd.h>

int execl(const char *path, const char *arg, …);

l–list:将参数一个一个传入execl*中

int execlp(const char *file, const char *arg, …);

p–path:不用告诉execl程序的路径,只需要告诉是谁,就会自动在环境变量PATH,进行可执行程序的查找

int execle , const char *arg, …,char *const envp[]);

e:环境变量

int execv(const char *path, char *const argv[]);

v–vector:可以将所有的执行参数,放入数组中,统一传递,而不用进行使用可变参数方案

int execvp(const char *file, char *const argv[]);

函数解释

这些函数如果调用成功则加载新的程序从启动代码开始执行,不再返回。

如果调用出错则返回-1

所以exec函数只有出错的返回值而没有成功的返回值

命名理解

这些函数原型看起来很容易混,但只要掌握了规律就很好记。

l(list) : 表示参数采用列表

v(vector) : 参数用数组

p(path) : 有p自动搜索环境变量PATH

e(env) : 表示自己维护环境变量

Linux--进程控制_linux int p=null,GitHub标星3.2K,2024年程序员学习,linux,github,运维

exec调用举例如下:

#include <unistd.h>

int main()

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注大数据)
Linux--进程控制_linux int p=null,GitHub标星3.2K,2024年程序员学习,linux,github,运维

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!文章来源地址https://www.toymoban.com/news/detail-855931.html

st char *arg, …);

p–path:不用告诉execl程序的路径,只需要告诉是谁,就会自动在环境变量PATH,进行可执行程序的查找

int execle , const char *arg, …,char *const envp[]);

e:环境变量

int execv(const char *path, char *const argv[]);

v–vector:可以将所有的执行参数,放入数组中,统一传递,而不用进行使用可变参数方案

int execvp(const char *file, char *const argv[]);

函数解释

这些函数如果调用成功则加载新的程序从启动代码开始执行,不再返回。

如果调用出错则返回-1

所以exec函数只有出错的返回值而没有成功的返回值

命名理解

这些函数原型看起来很容易混,但只要掌握了规律就很好记。

l(list) : 表示参数采用列表

v(vector) : 参数用数组

p(path) : 有p自动搜索环境变量PATH

e(env) : 表示自己维护环境变量

Linux--进程控制_linux int p=null,GitHub标星3.2K,2024年程序员学习,linux,github,运维

exec调用举例如下:

#include <unistd.h>

int main()

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注大数据)
[外链图片转存中…(img-Cel63yZL-1713307689713)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

到了这里,关于Linux--进程控制_linux int p=null,GitHub标星3.2K的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • Linux之进程(五)(进程控制)

    Linux之进程(五)(进程控制)

    目录 一、进程创建 1、fork函数创建进程 2、fork函数的返回值 3、fork常规用法 4、fork调用失败的原因 二、进程终止 1、进程终止的方式 2、进程退出码 3、进程的退出方法 三、进程等待 1、进程等待的必要性 2、wait函数 3、waitpid函数 四、进程程序替换 1、概念 2、原理 3、进程替

    2024年02月04日
    浏览(5)
  • [Linux 进程控制(二)] 进程程序替换

    [Linux 进程控制(二)] 进程程序替换

    首先,我们要认识到,我们之前fork()所创建的子进程,执行的代码,都是父进程的一部分(用if-else分流或者执行同样的代码)! 如果我们想让子进程执行新的程序呢? 执行全新的代码和访问全新的数据,不再和父进程有瓜葛,这种技术就叫做程序替换 ,下面我们就来学习一

    2024年03月14日
    浏览(23)
  • 【Linux】进程周边007之进程控制

    【Linux】进程周边007之进程控制

      👀 樊梓慕: 个人主页  🎥 个人专栏: 《C语言》 《数据结构》 《蓝桥杯试题》 《LeetCode刷题笔记》 《实训项目》 《C++》 《Linux》 🌝 每一个不曾起舞的日子,都是对生命的辜负 目录 前言 1.进程创建 2.进程终止 2.1探究main函数返回值 2.2探究普通函数退出的执行情况  

    2024年02月04日
    浏览(9)
  • 【Linux】Linux进程控制及程序替换

    【Linux】Linux进程控制及程序替换

    🍎 作者: 阿润菜菜 📖 专栏: Linux系统编程 在linux中fork是一个很重要的函数,它可以已存在进程中创建一个新进程。新进程为子进程,而原进程为父进程。 fork函数返回两个值,一个是子进程的进程号(pid),另一个是0。 父进程可以通过pid来区分自己和子进程,子进程可

    2024年02月02日
    浏览(26)
  • 【Linux】Linux进程控制 --- 进程创建、终止、等待、替换、shell派生子进程的理解…

    【Linux】Linux进程控制 --- 进程创建、终止、等待、替换、shell派生子进程的理解…

    柴犬: 你好啊,屏幕前的大帅哥or大美女,和我一起享受美好的今天叭😃😃😃 1. 在调用fork函数之后, 当执行的程序代码转移到内核中的fork代码后 ,内核需要分配 新的内存块 和 内核数据结构 给子进程, 内核数据结构包括PCB、mm_struct和页表,然后构建起映射关系 ,同时

    2024年01月16日
    浏览(10)
  • 【Linux进程控制】进程创建 | 进程终止 | 进程等待 | 进程替换

    【Linux进程控制】进程创建 | 进程终止 | 进程等待 | 进程替换

    【写在前面】 本文主要学习理解 fork 的返回值、写时拷贝的工作细节、为什么要存在写时拷贝;进程退出码、进程退出的场景及常见的退出方法、对比 man 2 _exit 和 man 3 exit;进程终止、操作系统怎么进行释放资源、池的概念;进程等待的价值、进程等待的方法 wait 和 waitpid

    2023年04月08日
    浏览(8)
  • linux入门之进程控制(上)进程创建,进程等待

    linux入门之进程控制(上)进程创建,进程等待

    目录 一、进程创建 1.fork函数 2.fork函数返回值 3.写时拷贝 4.fork常规用法 5.fork调用失败原因 二、进程终止 1.进程退出场景 2.进程常见退出方法 2.1_exit函数(直接调用内核) 2.2 exit函数 2.3return退出 三、进程等待 1.进程等待必要性 2.进程等待方法 2.1 wait方法 2.2 waitpid方法 2.3获取

    2024年02月12日
    浏览(11)
  • Linux--进程控制(2)--进程的程序替换(夺舍)

    Linux--进程控制(2)--进程的程序替换(夺舍)

    目录 进程的程序替换 0.相关函数 1.先看现象  2.解释原理 3.将代码改成多进程版  4.使用其它的替换函数,并且认识函数参数的含义 5.其它  关于进程替换我们需要了解的6个函数: 函数解释: 这些函数如果调用成功则加载新的程序从启动代码开始执行,不再返回。 如果调用出

    2024年04月29日
    浏览(10)
  • Linux-进程控制

    Linux-进程控制

    文章目录: 进程控制     为什么要有地址空间和页表     程序的内存       程序申请内存使用问题     写时拷贝与缺页中断       父子进程代码共享       为什么需要写时拷贝       页表的权限位       缺页中断     

    2024年04月08日
    浏览(5)
  • 深剖 Linux 进程控制

    深剖 Linux 进程控制

    小编是双非本科大一菜鸟不赘述,欢迎大佬指点江山,QQ - 1319365055 🎉🎉非科班转码社区诚邀您入驻🎉🎉 小伙伴们,打码路上一路向北,彼岸之前皆是疾苦 一个人的单打独斗不如一群人的砥砺前行 诚邀各位有志之士加入!! 直达: 社区链接点我 我们说进程调用 fork ,当

    2024年01月21日
    浏览(2)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包