C語(yǔ)言超詳細(xì)分析多進(jìn)程的概念與使用
1.多進(jìn)程相關(guān)概念
1.1什么是進(jìn)程
進(jìn)程:程序的一次執(zhí)行過(guò)程就會(huì)產(chǎn)生一個(gè)進(jìn)程。進(jìn)程是分配資源的最小單位(0-3G)。
進(jìn)程就是一個(gè)正在執(zhí)行的任務(wù)。進(jìn)程是一個(gè)動(dòng)態(tài)的過(guò)程,它有生命周期隨著程序的運(yùn)行
開(kāi)始,隨著程序結(jié)束而消亡。每個(gè)進(jìn)程都有自己的獨(dú)立的運(yùn)行的空間,比如每個(gè)進(jìn)程都有
自己的文件描述符,每個(gè)進(jìn)程都擁有自己的緩沖區(qū)。只要用戶(hù)執(zhí)行了一個(gè)程序,在內(nèi)核空間
就會(huì)創(chuàng)建一個(gè)task_struct的結(jié)構(gòu)體,這個(gè)結(jié)構(gòu)體就代表當(dāng)前的進(jìn)程。進(jìn)程運(yùn)行產(chǎn)生的所有
的信息都被放到這個(gè)結(jié)構(gòu)體中保存著。
1.2進(jìn)程和程序有什么區(qū)別
程序:程序是經(jīng)過(guò)編譯器編譯生成的二進(jìn)制文件,程序在硬盤(pán)上存儲(chǔ)。程序是靜態(tài)的,沒(méi)有生命
? 周期的概念程序本身不會(huì)分配內(nèi)存。
進(jìn)程:程序的一次執(zhí)行過(guò)程就會(huì)創(chuàng)建一個(gè)進(jìn)程,進(jìn)程是動(dòng)態(tài)的,有生命周期。進(jìn)程運(yùn)行的時(shí)候會(huì)
? 分配0-3G的內(nèi)存空間。進(jìn)程在內(nèi)存上存儲(chǔ)。
1.3進(jìn)程的組成
進(jìn)程是由三個(gè)部分組成的:進(jìn)程的PCB(task_struct),(程序段)文本段,數(shù)據(jù)段。
1.4進(jìn)程的種類(lèi)
交互進(jìn)程:這種進(jìn)程維護(hù)以一個(gè)終端,通過(guò)這個(gè)終端用戶(hù)可以和進(jìn)程進(jìn)程交互。
? 例如:文本編輯器
批處理進(jìn)程:這種進(jìn)程優(yōu)先級(jí)比較低,運(yùn)行的時(shí)候會(huì)被放到一個(gè)運(yùn)行的隊(duì)列中。
? 隨著隊(duì)列的執(zhí)行,而逐漸執(zhí)行。
? 例如gcc編譯程序的時(shí)候這個(gè)進(jìn)程就是批處理進(jìn)程。
守護(hù)進(jìn)程:守護(hù)進(jìn)程就是后臺(tái)運(yùn)行的服務(wù),隨著系統(tǒng)的啟動(dòng)而啟動(dòng),隨著系統(tǒng)的終止而終止。
? 例如:windows上的各種服務(wù)
1.5什么是進(jìn)程的PID
PID就是操作系統(tǒng)給進(jìn)程分配的編號(hào),它是識(shí)別進(jìn)程的唯一的標(biāo)識(shí)。
在linux系統(tǒng)中PID是一個(gè)大于等于0的值。
1.6特殊PID的進(jìn)程
0:idle:在linux系統(tǒng)啟動(dòng)的時(shí)候運(yùn)行的第一個(gè)進(jìn)程就是0號(hào)進(jìn)程。
? 如果沒(méi)有其他的進(jìn)程執(zhí)行就運(yùn)行這個(gè)idle進(jìn)程。
1:init:1號(hào)進(jìn)程是由0號(hào)進(jìn)程調(diào)用內(nèi)核kernel_thread函數(shù)產(chǎn)生的第一個(gè)進(jìn)程,
? 它會(huì)初始化所有的系統(tǒng)的硬件。當(dāng)初始化完之后會(huì)一直執(zhí)行,比如會(huì)為
? 孤兒進(jìn)程回收資源。
2:kthreadd:調(diào)度器進(jìn)程,主要負(fù)責(zé)進(jìn)程的調(diào)度工作。
1.7進(jìn)程的狀態(tài)
1.進(jìn)程運(yùn)行的狀態(tài)
D// 不可中斷的休眠態(tài)(信號(hào))
R//運(yùn)行態(tài)
S//可中斷的休眠態(tài)(信號(hào))
T//停止?fàn)顟B(tài)
X//死亡狀態(tài)
Z//僵尸態(tài)(進(jìn)程結(jié)束后沒(méi)有被父進(jìn)程回收資源)
2.進(jìn)程的附加狀態(tài)
<//高優(yōu)先級(jí)
N//低優(yōu)先級(jí)的進(jìn)程
L//在內(nèi)存區(qū)鎖定
s//會(huì)話組組長(zhǎng)
l//進(jìn)中包含多線程
+//前臺(tái)進(jìn)程
二.進(jìn)程實(shí)例
2.1進(jìn)程的拷貝
#include <head.h> int main(int argc,const char * argv[]) { for(int i=0;i<2;i++){ fork(); printf("-"); } return 0; }
原理圖:
分析:上述的程序會(huì)打印8個(gè)-,上述程序一共是4個(gè)進(jìn)程,因?yàn)樵谶M(jìn)程創(chuàng)建的時(shí)候會(huì)拷貝父進(jìn)程的
緩沖區(qū),由于2214和2215的緩沖區(qū)沒(méi)有刷新,所以2216和2217緩沖區(qū)中有兩個(gè)-。
2.2進(jìn)程創(chuàng)建的實(shí)例
#include <head.h> int main(int argc,const char * argv[]) { pid_t pid; pid = fork(); if(pid == -1){ PRINT_ERR("fork error"); }else if(pid == 0){ //子進(jìn)程 printf("這個(gè)就是子進(jìn)程\n"); }else{ //父進(jìn)程 printf("這個(gè)就是父進(jìn)程\n"); } return 0; }
分析圖:
2.3執(zhí)行沒(méi)有先后循序
#include <head.h> int main(int argc, const char* argv[]) { pid_t pid; pid = fork(); if (pid == -1) { PRINT_ERR("fork error"); } else if (pid == 0) { //子進(jìn)程 while (1) { sleep(1); printf("這個(gè)就是子進(jìn)程\n"); } } else { //父進(jìn)程 while (1) { sleep(1); printf("這個(gè)就是父進(jìn)程\n"); } } return 0; }
結(jié)果圖:
2.4進(jìn)程創(chuàng)建的實(shí)例(父子進(jìn)程內(nèi)存空間問(wèn)題)
父進(jìn)程fork產(chǎn)生子進(jìn)程的時(shí)候利用了寫(xiě)時(shí)拷貝的原則
2.5使用多進(jìn)程創(chuàng)建三個(gè)進(jìn)程
#include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <stdlib.h> int main(int argc, char const *argv[]) { pid_t pid; if((pid = fork()) ==-1){ printf("創(chuàng)建進(jìn)程失敗\n"); exit(-1); }else if(pid == 0){ pid_t tid; if((tid = fork())==-1){ printf("%d,%d\n",getpid(),getppid()); }else if(pid == 0){ printf("%d,%d\n",getpid(),getppid()); }else{ printf("%d\n",getpid()); } } while(1); return 0; }
2.6使用多進(jìn)程進(jìn)行拷貝文件
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <unistd.h> #include <sys/stat.h> #include <fcntl.h> char destfile[32]={0}; int get_length(char const *arcfile) { int fd,cd,length; if((fd=open(arcfile,O_RDONLY))==-1){ printf("open file error"); exit(-1); } snprintf(destfile,sizeof(destfile),"new_%s",arcfile); if((cd==open(destfile,O_WRONLY|O_TRUNC|O_CREAT,0666)==-1)){ } length = lseek(fd,0,SEEK_END); return length; } int copy_file(const char* srcfile,const char* destfile,int start,int length) { int sfd,dfd,ret,count = 0; char buff[128] = {0}; int counts=0; if((sfd=open(srcfile,O_RDONLY))==-1){ printf("open error"); } if((dfd=open(destfile,O_WRONLY))==-1){ printf("open file error"); } lseek(sfd,start,SEEK_SET); lseek(dfd,start,SEEK_SET); while (1){ ret = read(sfd,buff,sizeof(buff)); if(ret == 0){ break; } count+=ret; if(count >= length){ write(dfd,buff,length-(count-ret)); break; } write(dfd,buff,ret); } return 0; } int main(int argc, char const *argv[]) { pid_t pid; if(argc!=2){ printf("輸入格式錯(cuò)誤,請(qǐng)重新輸入\n"); exit(-1); } int length = get_length(argv[1]); if(length < 0){ printf("srcfile error\n"); return -1; } if((pid=fork())==-1){ printf("fork error"); exit(-1); }else if(pid == 0){ copy_file(argv[1],destfile,length/2,length-length/2); }else{ copy_file(argv[1],destfile,0,length/2); } return 0; }
三.什么是孤兒進(jìn)程與僵尸進(jìn)程
3.1僵尸進(jìn)程
子進(jìn)程結(jié)束之后,父進(jìn)程沒(méi)有為它回收資源,此時(shí)子進(jìn)程就是僵尸進(jìn)程
#include <head.h> int main(int argc, const char* argv[]) { pid_t pid; pid = fork(); if (pid == -1) { PRINT_ERR("fork error"); } else if (pid == 0) { //子進(jìn)程 } else { //父進(jìn)程 while(1); } return 0; }
3.2孤兒進(jìn)程
孤兒進(jìn)程:父進(jìn)程死掉之后,子進(jìn)程就是孤兒進(jìn)程,孤兒進(jìn)程被init進(jìn)程收養(yǎng)。
#include <head.h> int main(int argc, const char* argv[]) { pid_t pid; pid = fork(); if (pid == -1) { PRINT_ERR("fork error"); } else if (pid == 0) { //子進(jìn)程 printf("pid = %d\n",getpid()); while (1); } else { //父進(jìn)程 } return 0; }
四,守護(hù)進(jìn)程的創(chuàng)建
4.1守護(hù)進(jìn)程的創(chuàng)建
守護(hù)進(jìn)程:相當(dāng)于系統(tǒng)的服務(wù),隨著系統(tǒng)的啟動(dòng)而運(yùn)行,隨著系統(tǒng)的終止而終止。脫離了某個(gè)終端.
4.2步驟圖
4.3代碼實(shí)現(xiàn)
#include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <sys/stat.h> #include <fcntl.h> #include <stdlib.h> #define ERROR(msg) do{\ printf("%s %s %d\n",__FILE__,__func__,__LINE__);\ printf(msg);\ exit(-1); \ }while(0) int main(int argc, char const *argv[]) { pid_t pid; if ((pid == fork()) == -1){ ERROR("fork error"); }else if(pid == 0){ int fd; setsid(); chdir("/"); umask(0); for(int i = 3; i < getdtablesize(); i++){ close(i); } if((fd = open("my.log", O_RDWR, O_APPEND, O_CREAT, 0666)) == -1){ ERROR("open error"); } dup2(fd, 0); dup2(fd, 1); dup2(fd, 2); while(1){ sleep(1); printf("我是子進(jìn)程\n"); fflush(stdout); } }else{ printf("父親進(jìn)程已經(jīng)結(jié)束....\n"); exit(-1); } return 0; }
到此這篇關(guān)于C語(yǔ)言超詳細(xì)分析多進(jìn)程的概念與使用的文章就介紹到這了,更多相關(guān)C語(yǔ)言多進(jìn)程內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- C語(yǔ)言進(jìn)程程序替換的實(shí)現(xiàn)詳解
- C語(yǔ)言中進(jìn)程間通訊的方式詳解
- 詳解C語(yǔ)言進(jìn)程同步機(jī)制
- C語(yǔ)言實(shí)現(xiàn)進(jìn)程間通信原理解析
- C語(yǔ)言實(shí)現(xiàn)查看進(jìn)程是否存在的方法示例
- C語(yǔ)言中查詢(xún)進(jìn)程信號(hào)是否被遮罩或擱置的簡(jiǎn)單方法
- C語(yǔ)言中進(jìn)程信號(hào)集的相關(guān)操作函數(shù)詳解
- C語(yǔ)言中操作進(jìn)程信號(hào)的相關(guān)函數(shù)使用詳解
- C語(yǔ)言控制進(jìn)程之進(jìn)程等待詳解
相關(guān)文章
C++ 壓縮文件及文件夾方法 使用zlib開(kāi)源庫(kù)
下面小編就為大家分享一篇C++ 壓縮文件及文件夾方法 使用zlib開(kāi)源庫(kù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-03-03輸入3個(gè)字符串,將它們按照字母由大到小排序(示例代碼)
我們可以用string方法定義字符串變量。以下是具體實(shí)現(xiàn)代碼。需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助2013-10-10C語(yǔ)言開(kāi)發(fā)簡(jiǎn)易版掃雷小游戲
本文給大家分享的是一個(gè)使用C語(yǔ)言開(kāi)發(fā)的命令行下的簡(jiǎn)易版掃雷小游戲,本身沒(méi)有什么太多的技術(shù)含量,只不過(guò)是筆者的處女作,所以還是推薦給大家,希望對(duì)大家學(xué)習(xí)C能夠有所幫助。2015-12-12學(xué)習(xí)二維動(dòng)態(tài)數(shù)組指針做矩陣運(yùn)算的方法
這片文章介紹了如何利用二維動(dòng)態(tài)數(shù)組指針做矩陣運(yùn)算,需要的朋友可以參考下2015-07-07C語(yǔ)言尋找無(wú)向圖兩點(diǎn)間的最短路徑
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言尋找無(wú)向圖兩點(diǎn)間的最短路徑,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-01-01