【摘要】 介紹Linux下進(jìn)程概念、進(jìn)程信號捕獲、進(jìn)程管理相關(guān)的命令的使用等知識點(diǎn)。
任務(wù) 1: 進(jìn)程編程
1.1 進(jìn)程概念
./a.out //沒有運(yùn)行之前就是靜態(tài)程序,運(yùn)行之后就是一個(gè)進(jìn)程
怎么區(qū)分進(jìn)程?能夠獨(dú)立運(yùn)行的程序,main。
每個(gè)進(jìn)程都有自己唯一的PID號。
命令行可以通過ps命令獲取后臺進(jìn)程的PID號。
1.?示例:ps -e 查看后臺全部進(jìn)程
#include #include pid_t getpid(void); //獲取進(jìn)程PID pid_t getppid(void); |
??C語言代碼方式獲取PID
#include #include #include int main(int argc,char **argv) { pid_t pid=getpid(); printf("當(dāng)前進(jìn)程PID=%d ",pid); pid=getppid(); printf("PPID=%d \n",pid); return 0; } |
1.2 進(jìn)程的信號
kill 命令功能:給程序發(fā)送信號。
查看所有支持的信號:kill -l
kill [-s signal|-p] [--] pid... kill -l [signal] :查看指定信號的幫助信息 |
發(fā)送信號的方式:
1.?kill <進(jìn)程PID> //默認(rèn)發(fā)送的進(jìn)程終止信號,示例: #kill 348374
2.?kill -s <具體信號> <進(jìn)程的PID> 示例: #kill -s SIGINT 7646
3.?kill -<具體信號> <進(jìn)程的PID > 示例: # kill -SIGINT 7734
??信號的捕獲
#include typedef void (*sighandler_t)(int); sighandler_t signal(int signum, sighandler_t han-dler); int signum :要捕獲的信號 sighandler_t han-dler:函數(shù)指針 |
??信號的捕獲示例
#include #include #include #include void sighandler(int sig) { printf("捕獲的信號值=%d\n",sig); } int main(int argc,char **argv) { //將指定信號綁定到指定的函數(shù)上 signal(SIGINT,sighandler); //2 signal(SIGIO,sighandler); //29 signal(SIGSYS,sighandler); //31 while(1) { sleep(5); } return 0; } |
Linux系統(tǒng)和windows這些系統(tǒng)屬于非實(shí)時(shí)系統(tǒng)。 ucos\uclinux系統(tǒng)屬于實(shí)時(shí)系統(tǒng) |
??josb查看后臺運(yùn)行的程序作業(yè)代號。
??fg 1 將后臺作業(yè)代號為1的程序切換到前臺運(yùn)行
??當(dāng)程序在前臺運(yùn)行時(shí),按下 ctrl+z 可以將程序放入后臺,并且暫停運(yùn)行。
??bg 1 將后臺暫停的程序切換為運(yùn)行狀態(tài)
1.3 進(jìn)程的創(chuàng)建
#include #include #include #include int main(int argc,char **argv) { pid_t pid; pid=fork(); //創(chuàng)建一個(gè)新的進(jìn)程 if(pid==0) //子進(jìn)程 { printf("子進(jìn)程pid=%d\n",getpid()); } else if(pid>0) //父進(jìn)程 { printf("父進(jìn)程pid=%d\n",getpid()); } else //進(jìn)程創(chuàng)建錯(cuò)誤 { printf("進(jìn)程創(chuàng)建失敗!\n"); } return 0; } |
fork 函數(shù)創(chuàng)建新進(jìn)程本身屬于一個(gè)拷貝的過程。繼承功能!
??進(jìn)程的退出
#include #include #include #include #include void print(void); int main(int argc,char **argv) { print(); printf("main函數(shù)執(zhí)行!"); return 0; } void print(void) { printf("子函數(shù)執(zhí)行!"); //return; //終止函數(shù),會將緩沖區(qū)里的數(shù)據(jù)輸出 //exit(0); //直接終止進(jìn)程,會將緩沖區(qū)里的數(shù)據(jù)輸出 _exit(0); //強(qiáng)制終止進(jìn)程,銷毀緩沖區(qū)中的數(shù)據(jù) } |
??查看僵尸進(jìn)程:ps -aux
??查看系統(tǒng)的環(huán)境變量: env
??修改控制臺終端的環(huán)境變量:export PS1='[\u@\h \W \t]\$'
1.4 進(jìn)程的執(zhí)行
#include int system(const char *command); // “l(fā)s -l” …..”cd” |
接收命令的返回值:
#include int main(int argc,char **argv) { system("pwd >123.txt"); //獲取腳本或者其他程序的返回值 return 0; } |
??可變形參
#include void func(int data,...); int main(int argc,char **argv) { int data=888; func(data,123,456,789,100); return 0; } void func(int data,...) { int i=0; int *p=&data; for(i=0;i<5;i++) { printf("%d\n",*p++); } } |
??執(zhí)行進(jìn)程
#include #include int main(int argc,char **argv) { execl("/bin/ls","ls","-l",NULL); printf("123\n"); return 0; } #include #include int main(int argc,char **argv) { execlp("ls","ls","-l",NULL); //PATH=xxx:xxx:xxx: printf("123\n"); return 0; } |
??管道:FIFO--->先入先出
通過命令行: mkfifo命令可以直接創(chuàng)建FIFO文件。
無名管道的FIFO文件不是實(shí)體文件,存在內(nèi)存中的。
文件的方向: 即 fds[0]和讀端相對應(yīng), fds[1]和寫端相對應(yīng)
有名管道的FIFO文件是實(shí)體文件,存在硬盤中的。
#include #include /* #include int pipe(int pipefd[2]); */ int main(int argc,char **argv) { int pipefd[2]; char buff[100]; pipe(pipefd); //創(chuàng)建一個(gè)無名管道 [0]讀 [1]寫
int pid=fork(); if(pid) //父進(jìn)程 { while(1) { write(pipefd[1],"12345",6); sleep(1); } } else //子進(jìn)程 { while(1) { read(pipefd[0],buff,100); printf("buff=%s\n",buff); } } return 0; } |
1.5 練習(xí)
1. 練習(xí)無名管道的通信,刪除指定目錄下的指定后綴的文件。
要求:子進(jìn)程負(fù)責(zé)遍歷文件,父進(jìn)程就負(fù)責(zé)刪除文件。
#include
#include
#include
#include
/*
無名管道:
fds[0] 表示讀
fds[1] 表示寫
int dup2(int oldfd, int newfd); //實(shí)現(xiàn)文件描述符的重定向
示例: dup2(fds[1],1); //將本程序的標(biāo)準(zhǔn)輸出定義到管道的寫端
標(biāo)準(zhǔn)輸入:0
標(biāo)準(zhǔn)輸出:1
標(biāo)準(zhǔn)錯(cuò)誤:2
*/
int main(int argc,char **argv)
{
if(argc!=2)
{
printf("參數(shù)格式: ./app <傳入一個(gè)文件>\n");
exit(-1); //退出進(jìn)程
}
int fds[2]; //定義了管道文件
pipe(fds); //創(chuàng)建無名管道文件
char buff[100];
char cmd[100];
int status;
int pid=fork();
int len;
if(pid==0) //子進(jìn)程,遍歷目錄,查找文件
{
write(fds[1],argv[1],strlen(argv[1])); //寫入數(shù)據(jù)
/*
1. 定義一個(gè)二維數(shù)組,先將所有目錄遍歷完畢,將得到數(shù)據(jù)一次性寫過去
2. 遍歷一個(gè)就寫一個(gè)。(編寫一個(gè)應(yīng)答機(jī)制)
*/
}
else if(pid>0) //父進(jìn)程,負(fù)責(zé)刪除文件
{
len=read(fds[0],buff,100);
buff[len]='\0';
strcpy(cmd,"rm ");
strcat(cmd,"-rf ");
strcat(cmd,buff);
printf("cmd=%s\n",cmd);
system(cmd); //執(zhí)行最終的操作
wait(&status); //隨機(jī)等待一個(gè)子進(jìn)程退出
}
else
{
printf("進(jìn)程創(chuàng)建失敗!\n");
exit(-1);
}
return 0;
}
2. 練習(xí)命名管道的通信,刪除指定目錄下的指定后綴的文件。
要求:子進(jìn)程負(fù)責(zé)遍歷文件,父進(jìn)程就負(fù)責(zé)刪除文件。
dup2(fd_pipe[1],1); //將子進(jìn)程的標(biāo)準(zhǔn)輸出重定向到管道的寫端
3. (擴(kuò)展) 通過命名管道實(shí)現(xiàn)本地聊天室,一個(gè)終端界面表示一個(gè)用戶。
注明: 就一個(gè).c程序,運(yùn)行一個(gè)就是一個(gè)新的用戶,每個(gè)進(jìn)程之間通過命名管道通信。
(1) 每次運(yùn)行程序需要輸入用戶名創(chuàng)建用戶名。
(2) 每個(gè)新加入一個(gè)用戶有歡迎提示,例如: 歡迎xxx加入xxx聊天室。
(3) 可以互相發(fā)送內(nèi)容,發(fā)送內(nèi)容時(shí)的格式: <用戶名>: <實(shí)際內(nèi)容>:<發(fā)送的時(shí)間>
(4) 可以顯示在線人數(shù)。
(5) 一個(gè)用戶發(fā)送內(nèi)容,所有的用戶都可以顯示出來。
(6) 通過一個(gè)文件保存聊天記錄。
-
Linux
+關(guān)注
關(guān)注
87文章
11292瀏覽量
209322 -
編程
+關(guān)注
關(guān)注
88文章
3614瀏覽量
93685 -
進(jìn)程
+關(guān)注
關(guān)注
0文章
203瀏覽量
13960
發(fā)布評論請先 登錄
相關(guān)推薦
評論