国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁 > news >正文

廈門廣告公司有哪些aso優(yōu)化的主要內(nèi)容為

廈門廣告公司有哪些,aso優(yōu)化的主要內(nèi)容為,淄博住房和城鄉(xiāng)建設(shè)局網(wǎng)站,隨州抖音seo收費標(biāo)準(zhǔn)Linux進(jìn)程控制(2) 📟作者主頁:慢熱的陜西人 🌴專欄鏈接:Linux 📣歡迎各位大佬👍點贊🔥關(guān)注🚓收藏,🍉留言 本博客主要內(nèi)容講解了進(jìn)程等待收尾內(nèi)容和進(jìn)程的程序…

Linux進(jìn)程控制(2)

📟作者主頁:慢熱的陜西人

🌴專欄鏈接:Linux

📣歡迎各位大佬👍點贊🔥關(guān)注🚓收藏,🍉留言

本博客主要內(nèi)容講解了進(jìn)程等待收尾內(nèi)容和進(jìn)程的程序替換,以及進(jìn)程程序替換的原理,進(jìn)程程序替換的7個重要接口

文章目錄

  • Linux進(jìn)程控制(2)
    • 1.進(jìn)程等待(續(xù))
    • 2.進(jìn)程程序替換
      • 2.1 程序替換是如何完成的---單線程版
      • 2.2程序替換的原理
      • 2.3引入多進(jìn)程,使用所有程序替換的接口
        • 熟悉所有的替換程序接口(7個)

1.進(jìn)程等待(續(xù))

我們稍微改造一下,之前進(jìn)程等待的時候,父進(jìn)程不要阻塞等待的代碼,讓父進(jìn)程真正的去運行一些任務(wù)。

我們采用函數(shù)回調(diào)的方式,讓父進(jìn)程在等待子進(jìn)程的時候也可以去運行自己的一些任務(wù)!

#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<stdlib.h>#define TASK_NUM 10//預(yù)設(shè)一批任務(wù)
void sync_disk()
{printf("這是一個刷新數(shù)據(jù)的任務(wù)\n");
}void sync_log()
{printf("這是一個同步日志的任務(wù)\n");
}void net_send()
{printf("這是一個網(wǎng)絡(luò)發(fā)送的任務(wù)\n");
}                                                                                                                                                            //保存相關(guān)的任務(wù)
typedef void (*func_t)(); //定義了一個函數(shù)指針類型
func_t orther_task[TASK_NUM] = {NULL}; //裝載任務(wù)
int Load_Task(func_t fuc)
{int i = 0;for(; i < TASK_NUM; ++i){if(orther_task[i] == NULL) break;}if(TASK_NUM == i) return -1;else orther_task[i] = fuc;return 0;
}//初始化函數(shù)指針數(shù)組
void Init_Task()
{for(int i = 0; i < TASK_NUM; ++i) orther_task[i] = NULL;Load_Task(sync_disk);  Load_Task(sync_log);Load_Task(net_send);
}void Run_Task()
{for(int i = 0; i < TASK_NUM; ++i){if(orther_task[i] == NULL) continue;else orther_task[i]();}
}int main()
{pid_t id = fork();if(id == 0){//子進(jìn)程int cnt = 5;while(cnt){printf("我是子進(jìn)程,我還活著呢,我還有%dS,我的pid:%d,我的ppid:%d\n", cnt--, getpid(), getppid());sleep(1);}exit(0);}Init_Task();while(1){int status = 0;pid_t ret_id = waitpid(id, &status, WNOHANG);// 夯住了if(ret_id < 0){printf("waitpid_error\n");}else if(ret_id == 0){Run_Task();                                                                                                                                          sleep(1);continue;}else{printf("我是父進(jìn)程,我等待成功了,我的pid:%d,我的ppid:%d, ret_id: %d, child exit code: %d, child exit signal:%d\n",getpid(), getppid(), ret_id, (status >> 8)&0xFF, status & 0x7F);exit(0);}sleep(1); }return 0;
}

運行結(jié)果:

image-20231109151934831

繼續(xù)改進(jìn),我們之前獲取進(jìn)程退出碼的時候是使用(status >> 8)& 0xFF的方式來進(jìn)行獲取的,那么實際上C庫也給我們提供了兩個宏來幫助我們獲取進(jìn)程的退出碼:

status:
WIFEXITED(status): 若為正常終止子進(jìn)程返回的狀態(tài),則為真。(查看進(jìn)程是否是正常退出)
WEXITSTATUS(status): 若WIFEXITED非零,提取子進(jìn)程退出碼。(查看進(jìn)程的退出碼)

我們用這兩個宏來優(yōu)化一下我們等待成功,也就是子進(jìn)程結(jié)束的時候的代碼:

      else                                                                                       {                                                                                            //等待成功                                                                                   if(WIFEXITED(status))                                                       {                                                                                         //正常退出                                                                                 printf("wait success, child exit code :%d", WEXITSTATUS(status));                           }                                                                                             else {                                                                                             //異常退出                                                                                printf("wait success, child exit signal :%d", status & 0x7F);    }            exit(0);    }   

正常退出:

image-20231109153300831

異常退出:我們嘗試在父進(jìn)程等待的時候殺掉子進(jìn)程:

image-20231109153505131

2.進(jìn)程程序替換

我們?yōu)槭裁葱枰獎?chuàng)建子進(jìn)程?為了讓子進(jìn)程幫我執(zhí)行特定的任務(wù);

①讓子進(jìn)程執(zhí)行父進(jìn)程的一部分代碼;

②如果子進(jìn)程指向一段全新的代碼呢?這時候我們就需要進(jìn)程的程序替換!

也是為什么需要進(jìn)程的程序替換。

2.1 程序替換是如何完成的—單線程版

代碼:

#include<stdio.h>    
#include<stdlib.h>    
#include<unistd.h>    int main()    
{    printf("begin......\n");    printf("begin......\n");    printf("begin......\n");    printf("begin......\n");    printf("begin......\n");    execl("/bin/ls", "ls", "-a", "-l", NULL);                                                           printf("end........\n");    printf("end........\n");    printf("end........\n");    printf("end........\n");    printf("end........\n");    return 0;    
}  

運行結(jié)果:

那么我們可以看到這個進(jìn)程運行了開始的begin....,然后運行了ls,但是后面的end...卻不見了。

這是因為發(fā)生了進(jìn)程的程序的替換,簡要的原理就是,操作系統(tǒng)通過提供的地址/bin/ls從磁盤中拿出ls然后選到指定的文件ls,在輸入一些參數(shù)-a, -l,以NULL表示結(jié)束。

image-20231109162541803

2.2程序替換的原理

操作系統(tǒng)不動當(dāng)前進(jìn)程的內(nèi)核數(shù)據(jù)結(jié)構(gòu),而是去磁盤內(nèi)部拿到要替換的數(shù)據(jù)和代碼,將我們當(dāng)前進(jìn)程的數(shù)據(jù)和代碼替換掉。

當(dāng)進(jìn)程調(diào)用一種exec函數(shù)時,該進(jìn)程的用戶空間代碼和數(shù)據(jù)完全被新程序替換,從新程序的啟動例程開始執(zhí)行。

所以進(jìn)程的程序替換,是沒有創(chuàng)建新的進(jìn)程的。

image-20231109163349868

①站在進(jìn)程的角度

操作系統(tǒng),幫我們在磁盤內(nèi)部找到我們要替換的數(shù)據(jù)和代碼,替換進(jìn)程的數(shù)據(jù)和代碼。

②站在程序的角度

這個程序被加載了,所以我們也稱execl這類函數(shù)為加載器

我們在回到一開始,為什么我們程序后面的end.....卻沒有打印出來?

image-20231109164919209

原因是當(dāng)我們加載程序替換的時候,新的數(shù)據(jù)和代碼就進(jìn)入了進(jìn)程,當(dāng)前進(jìn)程后續(xù)沒有沒運行的代碼就成為了老代碼,直接被替換了,沒有機(jī)會執(zhí)行了。

所以進(jìn)程的程序替換是整體替換,而不是局部替換。

所以我們接下來引入多進(jìn)程的程序替換

2.3引入多進(jìn)程,使用所有程序替換的接口

例程:

#include<stdio.h>    
#include<stdlib.h>    
#include<unistd.h>    
#include<sys/types.h>    
#include<sys/wait.h>    int main()    
{    pid_t id = fork();    if(id == 0)    {    //child    printf("我是子進(jìn)程:%d", getpid());    execl("/bin/ls", "ls", "-a", "-l", NULL);    }    sleep(2);    //father    waitpid(id, NULL, 0);    printf("我是父進(jìn)程:%d\n", getpid());                                                                                                                      return 0;    
}

運行結(jié)果:

我們看到execl之后父進(jìn)程的內(nèi)容也被運行了

因為進(jìn)程的獨立性,所以進(jìn)程的程序替換只會影響調(diào)用程序替換的子進(jìn)程。

子進(jìn)程加載新程序的時候,是需要進(jìn)行程序替換的,發(fā)生寫時拷貝(子進(jìn)程執(zhí)行的可是全新的代碼啊,新的代碼,所以代碼區(qū)也可以發(fā)生寫時拷貝)

image-20231109172035019

那么對于execl這類加載函數(shù),它有沒有返回值呢?

答案是分情況:

①替換成功是沒有返回值的

②替換失敗是有返回值的-1

原因是:假設(shè)替換替換成功了,那么我們該進(jìn)程中的代碼和數(shù)據(jù),都會被替換成新的代碼和數(shù)據(jù),那么我們之前的返回值也就不復(fù)存在了,并且我們也不需要返回值了。

替換失敗的情況下,進(jìn)程之前的代碼和數(shù)據(jù)還是存在的,那么我們的返回值也是存在的,從而可以返回。

所以我們調(diào)用了加載函數(shù)之后我們不用去判斷它是否加載成功,只需要在函數(shù)后面返回異常即可。

失敗的例程:

#include<stdio.h>    
#include<stdlib.h>    
#include<unistd.h>    
#include<sys/types.h>    
#include<sys/wait.h>    int main()    
{    pid_t id = fork();    if(id == 0)    {    //child    printf("我是子進(jìn)程:%d\n", getpid());                                                                                                                    execl("/bin/lsss", "lsss", "-a", "-l", NULL);    exit(1);    }    sleep(2);    //father    int status;    waitpid(id,&status, 0);    printf("我是父進(jìn)程:%d, child exit signal:%d\n", getpid(), WEXITSTATUS(status));    return 0;    
} 

image-20231109173257987

熟悉所有的替換程序接口(7個)

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

例如:execl("/bin/ls", "ls", "-a", "-l", NULL);

l代表list;

path:路徑,也就是告訴操作系統(tǒng),你要用來替換的程序,在磁盤的哪個路徑,例程里的/bin/ls

arg:文件,是你要用來替換的文件名,例程里面的ls。

其中的...是可變參數(shù)列表,例程中的那些參數(shù)-a , -l。

其中最后我們要特別的輸入一個NULL參數(shù),告訴函數(shù)參數(shù)結(jié)束了;

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

相比較第一個函數(shù)的差別就是,第一個函數(shù)要求我們一個一個的去傳參數(shù),而第二個要求我們直接用數(shù)組的形式去傳,但是原則也是一樣的,數(shù)組的最后一個元素也要置成NULL

我們在子進(jìn)程內(nèi)部調(diào)用的時候是這樣的:

先創(chuàng)建一個數(shù)組,將這些參數(shù)一個一個放進(jìn)去,再傳給execv即可

那么其實v就是vector就是數(shù)組的意思;

   char* const argv[] =    {    "ls",    "-a",    "-l",    NULL    };    // execl("/bin/lsss", "lsss", "-a", "-l", NULL);    execv("/bin/ls", argv);                                                                                                                                 exit(1);    }    

運行結(jié)果:

image-20231109175259752

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

p:當(dāng)我們指定執(zhí)行程序的時候,只需要指定程序名即可,系統(tǒng)會自動在**環(huán)境變量PATH**中查找。

也就是說我們要用于替換的程序,必須在環(huán)境變量PATH中,或者說我們在環(huán)境變量PATH中設(shè)置過;

 execlp("ls", "ls", "-a", "-l", NULL);    

image-20231109180335737

那么其中的兩個ls是不一樣的,一個是文件名,一個是參數(shù)。

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

v:表示參數(shù)以數(shù)組的形式傳入;

p:表示在環(huán)境變量PATH中去尋找用于替換的文件;

   char* const argv[] =                                                                                                                                   {    "ls",    "-a",    "-l",    NULL    };    execvp("ls", argv);    

運行結(jié)果:

image-20231109181025149

int execle(const char *path, const char *arg, ..., char * const envp[]);

envp[]:叫做自定義環(huán)境變量,當(dāng)我們不想使用系統(tǒng)默認(rèn)的環(huán)境變量的時候,這個時候我們就傳遞一個envp

比如我們現(xiàn)在要讓我們的調(diào)用exec目錄下的ortherproc來替換myproc的子進(jìn)程的后續(xù)代碼

image-20231109182618129

先用execl嘗試一下:

 execl("./exec/ortherproc", "ortherproc", NULL);  

運行結(jié)果:

image-20231109182932018

換成的動態(tài)的效果再看看:

動態(tài)效果

下來我們嘗試用execle來實現(xiàn)一下:

proc.c

   char* const envp[] =                                                                                                             {                                                                                                                                "MYENVP=UCanCMe!",    NULL    };    execle("./exec/ortherproc", "ortherproc",envp);  

ortherproc.cc

for(int i = 0; i < 5; ++i)      
{      cout << "我是另一個程序,我的PID是 :" << getpid() << endl;      cout << "MYENVP: " << (getenv("MYENVP")==NULL ? "NULL" : getenv("MYENVP")) << endl;           cout << "PATH: " << (getenv("PATH") == NULL ? "NULL" : getenv("PATH")) << endl;      sleep(1);                                                                     
}     

運行結(jié)果:

我們看到自定環(huán)境變量打印出來了,但是操作系統(tǒng)內(nèi)部的環(huán)境變量卻不見了,所以我們可以得到一個結(jié)論:

自定義環(huán)境變量覆蓋了,默認(rèn)的環(huán)境變量;

image-20231109193230574

我們傳默認(rèn)的環(huán)境變量試試:

extern char ** environ;execle("./exec/ortherproc", "ortherproc",NULL , environ);  

運行結(jié)果:

image-20231109193621091

那么如果我們兩個都要呢,那么有一個接口putenv給我們提供了一個將自定義環(huán)境變量追加到進(jìn)程的默認(rèn)環(huán)境變量的方法:接下來我們嘗試一下

   putenv("MYENVP=UCanCMe");    execle("./exec/ortherproc", "ortherproc", NULL, environ);  

運行結(jié)果:

image-20231109201734620

插播一段

我們知道環(huán)境變量具有全局屬性,可以被子進(jìn)程繼承下去,那么操作系統(tǒng)是怎么辦到的?

只需要用execle的最后一個參數(shù)傳過去即可!

那么我們是不是不需要putenv也能實現(xiàn)兩個都能被子進(jìn)程讀取到呢?

我們直接把自定義的環(huán)境變量exportbash中試試:

[mi@lavm-5wklnbmaja lesson6]$ export MYENVP=UCanCMe
[mi@lavm-5wklnbmaja lesson6]$ echo $MYENVP
UCanCMe

運行結(jié)果:

我們發(fā)現(xiàn)是可行的,自定義環(huán)境變量-----> bash ----->父進(jìn)程------>子進(jìn)程

image-20231109202438896

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

p:不需要指定路徑,只要在環(huán)境變量內(nèi)部即可;

v:參數(shù)以數(shù)組的形式傳入;

e:環(huán)境變量數(shù)組傳入;

使用方法都與上面的類似。

int execve(const char *filename, char *const argv[], char *const envp[]);

這個接口也不用過多介紹了,使用方法都是一樣的。

那么我們需要注意的是,在linux的man手冊中將區(qū)域六個接口都放在了3號手冊,唯獨這個卻放在了2號手冊。

其實操作系統(tǒng)只給我們提供了一個程序替換的接口execve,剩下的幾個接口都是由這個接口封裝出來的。

image-20231109204020146

并且我們程序替換的時候不僅可以替換C語言的,甚至其他的語言都可以替換,我上面的例子也做到了用C++替換,因為這些代碼都是交給操作系統(tǒng)來處理的而不是編譯器,所以不論是什么語言都是可以替換的!

到這本篇博客的內(nèi)容就到此結(jié)束了。
如果覺得本篇博客內(nèi)容對你有所幫助的話,可以點贊,收藏,順便關(guān)注一下!
如果文章內(nèi)容有錯誤,歡迎在評論區(qū)指正

在這里插入圖片描述

http://aloenet.com.cn/news/29156.html

相關(guān)文章:

  • wordpress修改谷歌外貿(mào)seo公司
  • 做美團(tuán)網(wǎng)這種網(wǎng)站賺錢嗎亞馬遜關(guān)鍵詞搜索器
  • 英語網(wǎng)站建設(shè)如何制作一個公司網(wǎng)站
  • 上海網(wǎng)站建設(shè)平臺站霸網(wǎng)絡(luò)seo學(xué)習(xí)網(wǎng)站
  • 做網(wǎng)站有一個火箭回頂部網(wǎng)站優(yōu)化關(guān)鍵詞公司
  • 做cpa的博客網(wǎng)站類型博客網(wǎng)
  • 優(yōu)惠券推廣網(wǎng)站怎么做seo怎么搞
  • nas網(wǎng)站怎么做網(wǎng)站時事新聞最新2022
  • 順德樂從有做阿里巴巴的網(wǎng)站嗎sem競價專員是干什么的
  • 做網(wǎng)站視頻圖片加載不出來企業(yè)網(wǎng)站模板下載
  • 情感視頻素材網(wǎng)站劉連康seo培訓(xùn)哪家強(qiáng)
  • 網(wǎng)站建設(shè)和網(wǎng)站推廣可以同一家做嗎網(wǎng)站優(yōu)化排名金蘋果系統(tǒng)
  • 企業(yè)網(wǎng)站建設(shè)英文超級外鏈
  • 手機(jī)網(wǎng)站哪家好西安百度推廣優(yōu)化
  • 網(wǎng)站開發(fā) 英文文章百度收錄快的發(fā)帖平臺
  • 福州網(wǎng)頁鄭州seo排名優(yōu)化公司
  • 汕頭網(wǎng)站建設(shè)制作公司衡陽seo快速排名
  • 分類信息網(wǎng)站成都搭建如何搭建一個網(wǎng)站平臺
  • 做網(wǎng)站的點子站長之家ppt素材
  • 同程網(wǎng)站建設(shè)分析朝陽網(wǎng)站建設(shè)公司
  • 深圳住建委網(wǎng)站智謀網(wǎng)站優(yōu)化公司
  • html5門戶網(wǎng)站模板百度人工客服電話多少
  • 鄭州做網(wǎng)站九零后排名點擊工具
  • 網(wǎng)站開發(fā)程序員 工資百度云怎么找資源
  • 貴陽網(wǎng)站建設(shè)多少錢?影視后期培訓(xùn)機(jī)構(gòu)全國排名
  • 如何搭建公司網(wǎng)站上海公關(guān)公司
  • 做美圖 網(wǎng)站有哪些付費惡意點擊軟件
  • 做局域網(wǎng)網(wǎng)站教程東莞網(wǎng)絡(luò)優(yōu)化調(diào)查公司
  • 慈溪企業(yè)排名網(wǎng)站培訓(xùn)機(jī)構(gòu)排名全國十大教育機(jī)構(gòu)排名
  • 做腳本網(wǎng)站建站公司最新報價