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能夠現實父子關系和cmd 5)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 exec int 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表示正常退出,其它數表示出現錯誤,進程非正常結束版權聲明:本文博客原創文章,博客,未經同意,不得轉載。
轉載于:https://www.cnblogs.com/yxwkf/p/4674671.html
總結
以上是生活随笔為你收集整理的Linux 多学习过程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [转帖]FPGA--Vivado
- 下一篇: 如何附加数据库