Linux 多進程學習,Linux進程學習

來源:互聯網
上載者:User

Linux 多進程學習,Linux進程學習
1Linux進程概述進程是一個程式執行一次的過程,他和程式有著本質的區別。程式是靜態,他是一些儲存在磁碟上的指令有序的集合。進程是動態概念,他是運行者的程式,包含進程的動態建立,調度和消亡,是Linux的基本調度單位。進程式控制制塊(PCB)是進程的靜態描述,包括進程的描述資訊,進程的控制資訊,以及資源資訊時間片:他輪流在每個進程的得到的時間片用完後從進程那裡千回控制權
1.1進程標識os會為每一個進程分配一個唯一的盛行ID,作為進程的標識號(pid),還有父進程ID(ppid)所有的進程的祖先都是同一個進程init進程,ID為1通過getpid(),getppid() 得到進程的pid,ppid執行個體:printf("pid:%d ppid:%d\n",getpid(),getppid());
1.2進程的使用者ID與組ID

進程運行過程中必須有類似於使用者的身份,哪個使用者就是該使用者的身份,就是那個使用者的組可用getuid(),getgid();獲得進程還有有效使用者ID和有效組ID,缺少的情況下,與真實ID相同,可以用geteuid(),getegid();檔案許可權有S的時候,有效ID是進程的所有者(建立者),否則有效ID就是程式的運行者,與真實ID相同
ps -aux查看所有使用者進程的許可權,cpu,和記憶體的使用方式
ps -ef 查看使用者操作的PID與PPID 與CMD(命令列)
1.3進程的狀態執行態,就緒態,等待態
1.4LInux下的進程結構Linux中的進程包含三個段:資料區段,程式碼片段,堆棧段資料區段:(普通資料區段)全域變數,常熟(bbs資料區段)為初始化的全域變數以及(堆)動態資料分配的資料空間程式碼片段:存放程式碼的資料堆棧段:子程式的返回地址,子程式的參數,程式的局部變數


1.5LInux下的進程管理

進程process:是os的最小單位1)ps查看活動進程2)ps -aux查看所有進程%cpu,%mem stat狀態(S睡眠T暫停R運行Z殭屍)3)ps -aux|grep'aa' 尋找指定的(aa)進程4)ps -ef可以現實父子關係和cmd5)top現實前20條的進程,動態改變6)./my_add 可能要運行很長時間,按ctrl+z可以把京城暫停,在執行  bg作業ID 可以將該進程帶入後台運行例如:[1]+ ./my_add 1 34 &  ,&表示該進程在後台正在運行。利用jods可以查看背景工作fg作業ID 把後台人物帶到前台7)kill -9 進程號(PID) 殺掉該進程  ,pkill a 進程名
2 進程的建立Linux下有四類建立子進程的函數:system(),fork(),exec*(),popen();2.1system函數system函數system括弧裡面放的是命令,也就是cmd 例子如下:
#include<iostream>#include<stdlib.h>#include<string.h>#include<stdio.h>using namespace std;int main(int argc,char *argv[]){char cmd[1024]="";for(int i=1;i<argc;i++){strcat(cmd,argv[i]);strcat(cmd," ");}puts(cmd);int ans;ans=system(cmd);printf("%x\n",ans);}
用system調用其他可執行程式,並輸入參數 輸入例如: ./main ./my_add  其中my_add計算兩個數之和其中計算結果在system的返回值高位元組上:ret00,所以直接出256
int main(int argc,char *argv[]){if(argc!=2){printf("failed\n");return 0;}int left,right;char cmd[1024]="";char line[1024]="";strcat(cmd,argv[1]);strcat(cmd," ");while(printf(">>"),scanf("%d %d",&left,&right)){memset(line,0,sizeof(line));sprintf(line,"%s %d %d",argv[1],left,right);strcpy(cmd,line);int ret;ret=system(cmd);printf("result:%d\n",ret/256);}}
2.2fork函數fork函數在以存在的進程中建立一個新的進程,新的進程作為子進程,原進程為父進程父進程的返回值是子進程,子進程的返回值是0.fork建立子進程是完全複製父進程,而且緩衝區也複製元進程和子京城都從函數fork返回,在各自繼續圓形下去,但是元函數的fork返回值是子進程的pid,而在子進程中fork返回0,返回-1表示建立失敗
#include<iostream>#include<unistd.h>#include<stdlib.h>#include<stdio.h>using namespace std;int main(int argc,char *argv[]){pid_t pid;int i=3;printf("hello\n");pid=fork();fflush(stdout);//兒子複製的時候將緩衝區也複製了,如果沒有這句話,上面的hello將出現兩便if(pid>0){printf("parents:pid:%u,ret:%u,pp:%u\n",getpid(),pid,getppid());}else if(pid==0){//sleep(5);printf("child:pid:%u,ret:%u,pp:%u\n",getpid(),pid,getppid());}printf("bye!\n");}

2.3exec函數exec函數是用exec的第一個參數制定的程式覆蓋現有的進程空間,也就是說執行exec族函數之後,他後面的所有代碼不再執行詳細使用方法 在終端輸入man execint execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg,..., char * const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[], char *const envp[]);
其中path是包含執行檔案名稱的全路徑名,多個參數時,注意後面最後一個參數必須為NULL,arg是可執行檔的命令列參數
int execl(const char *path, const char *arg, ...);例如:
if(execl("/home/yang/0820/my_exec/","my_add","3","2",NULL)==-1){perror("execl error");}
int execlp(const char *file, const char *arg, ...);例如:
if(execlp("./my_add","my_add","fwef","fwe","fewgeraf",NULL)==-1){perror("execlp error");}
int execv(const char *path, char *const argv[]);例如:

char *args[10];args[0]="my_add";args[1]="12";args[2]="23";args[3]=NULL;if(execv("/home/yang/0820/my_exec/my_add",args)==-1){perror("execl:");}

2.4popen函數(以後補充)popen函數類似system函數,與system不同之處在於它使用管道操作,原型為#include<stdio.h>

FILE*popen(const char *command, const char *type);

int pclose(FILE *stream);

command為可執行檔的全路徑和執行參數,type選擇性參數為“r” 或“w”“w”popen返回的檔案流作為新的進程(例如my_add.exe)標準輸入資料流,即stdin“r”popen返回的檔案流作為新進程的標準輸出資料流 stdout,也就是說popen只改變新進程的標準輸入資料流或者標準輸出資料流popen的詳細流程:type為“r”,(即command命令的執行結果作為當前進程的輸入結果),調用程式利用popen函數返回FILE*檔案流指標,就可以通過常用的stdio庫如fgets,來讀取被調用函數的輸出。如果type是“w”(即當前的程式的輸出結果作為commend命令的輸入),調用程式可以用fwrite想調用程式發送資料,而被調用的程式可以在自己的標準輸入上讀取這些資料例子:主程式螢幕輸出:
FILE *fp;char a[1000];char b[1000];char cmd[1024]="";printf("plseas write\n");fgets(a,1000,stdin);sprintf(cmd,"%s %s",argv[1],a);fp=popen(cmd,"r");//這個指令cmd為可執行檔的全路經fgets(b,1000,fp);printf("%s\n",b);

新進程螢幕輸出:
FILE *fp;char a[1000];gets(a);fp=popen(argv[1],"w");fputs(a,fp);pclose(fp);

3.進程式控制制與終止用fork函數啟動一個子進程時,子進程就有了自己的生命獨立運行了 孤兒進程:如果父進程先於子進程退出,子進程就變成了孤兒進程(通常是父進程負責釋放子進程的記憶體空間),此時將自動被PID為1的進程(即init)接管。孤兒進程退出後,它的清理工作由祖先進程init自動處理 殭屍進程:子進程退出,系統不會自動清理掉子進程的工作環境,必須有父進程調傭wait或waitpid函數來完成清理工作,如果父進程不做清理工作,一經推出的子進程就會成為殭屍進程,系統中如果殭屍進程過多就會影響系統效能函數原型:#include<sys/types.h>#include<sys/wait.h>pid_t wait(int *status);pid_t waitpid(pid_t pid,int *status,int options); wait函數隨機等待一個已經退出的子進程,並返回該子進程的pid waitpid等待制定pid的子進程,如火為-1表示等待所有子進程 status參數是傳出參數,存放子進程的退出狀態 options用於改變waitpid的行為,其中最重要的是WNOHANG,它表示無論子進程是否有退出都立即返回產生殭屍進程例子:
#include <stdio.h>#include <stdlib.h>#include <unistd.h>main(){    pid_t pid = fork();    if( pid == 0 )    {        exit(10);    }    else    {sleep(10);    }}
避免殭屍進程例子:
#include <stdio.h>#include <stdlib.h>#include <unistd.h>main(){    pid_t pid = fork();    if( pid == 0 )    {        exit(10);    }    else    { wait(NULL);    //NULL表示等待所有進程 sleep(10);//通常要將sleep放在wait的後面,要不然也會出現殭屍進程    }}

3.2進程的終止5種方式終止:1) main函數自然返回2)調用exit函數3)調用_exit函數調用abort函數接受能導致進程終止的訊號ctrl + c exit與_exit區別:exit會處理緩衝區的內容,_exit不會處理緩衝區的內容

exit和_exit函數的原型:

#include<stdlib.h> //exit的標頭檔

#include<unistd.h> //_exit的標頭檔

void  exit(int status);

void_exit(int status);

status是一個整型的參數,可以利用這個參數傳遞進程結束是的狀態,0表示正常退出,其他數表示出現錯誤,進程非正常結束








































linux學習的步驟?

教你一個快樂中學習linux的方式,就是安裝Fedora系統,要自己親手安裝,然後根據教程用命令配置你的linux系統,這裡為什麼說讓你安裝fedora系統呢,就是因為此系統是命令操作為主的,能讓你更好的得到鍛煉,系統安裝好後,你只要用這個系統進行各種操作就可以了,例如看電影 聽音樂 聊QQ等等,前提是這些軟體你要手動去用命令去linux源安裝,在這些玩,用的過程中,你的linux知識不知不覺就提高了.遇到不會的操作就多找找教程,我覺得這個學習沒有步驟,因為你在使用linux系統時,對於linux 的知識已經在不斷加深了. 純手打,比較有誠意,複製一大篇根本沒意義.
 
[Linux]多進程編程

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

int main(void)
{
int i = 0;
int *nCount;
int pfd[2];
char szBuff[11] = {0};
int status;
pid_t pid;

pipe(pfd);

if (fork() == 0)
{
nCount = malloc(sizeof(int) * 10);
for (i = 0; i < 10; ++i)
{
nCount[i] = i;
sprintf(szBuff, "%s%d", szBuff, nCount[i]);
}

write(pfd[1], szBuff, strlen(szBuff));
free(nCount);
close(pfd[0]);
close(pfd[1]);
}
else
{
if (fork() == 0)
{
printf("sleep (5) !\n");
sleep(5);
read(pfd[0], szBuff, 10);
printf("%s\n", szBuff);
close(pfd[0]);
close(pfd[1]);
}
else
{
pid = wait(&status);
i = WEXITSTATUS(status);
printf("child is %d ,exit status =%d\n", pid, i);
pid = wait(&status);
i = WEXITSTATUS(status);
pr......餘下全文>>
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.