【摘要】 介紹Linux下進(jìn)程概念、進(jìn)程信號(hào)捕獲、進(jìn)程管理相關(guān)的命令的使用等知識(shí)點(diǎn)。
任務(wù) 1: 進(jìn)程編程
1.1 進(jìn)程概念
./a.out //沒(méi)有運(yùn)行之前就是靜態(tài)程序,運(yùn)行之后就是一個(gè)進(jìn)程
怎么區(qū)分進(jìn)程?能夠獨(dú)立運(yùn)行的程序,main。
每個(gè)進(jìn)程都有自己唯一的PID號(hào)。
命令行可以通過(guò)ps命令獲取后臺(tái)進(jìn)程的PID號(hào)。
1.?示例:ps -e 查看后臺(tái)全部進(jìn)程
#include #include pid_t getpid(void); //獲取進(jìn)程PID pid_t getppid(void); |
??C語(yǔ)言代碼方式獲取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)程的信號(hào)
kill 命令功能:給程序發(fā)送信號(hào)。
查看所有支持的信號(hào):kill -l

kill [-s signal|-p] [--] pid... kill -l [signal] :查看指定信號(hào)的幫助信息 |
發(fā)送信號(hào)的方式:
1.?kill <進(jìn)程PID> //默認(rèn)發(fā)送的進(jìn)程終止信號(hào),示例: #kill 348374
2.?kill -s <具體信號(hào)> <進(jìn)程的PID> 示例: #kill -s SIGINT 7646
3.?kill -<具體信號(hào)> <進(jìn)程的PID > 示例: # kill -SIGINT 7734
??信號(hào)的捕獲
#include typedef void (*sighandler_t)(int); sighandler_t signal(int signum, sighandler_t han-dler); 參數(shù): int signum :要捕獲的信號(hào) sighandler_t han-dler:函數(shù)指針 |
??信號(hào)的捕獲示例
#include #include #include #include void sighandler(int sig) { printf("捕獲的信號(hào)值=%d\n",sig); } int main(int argc,char **argv) { //將指定信號(hào)綁定到指定的函數(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查看后臺(tái)運(yùn)行的程序作業(yè)代號(hào)。
??fg 1 將后臺(tái)作業(yè)代號(hào)為1的程序切換到前臺(tái)運(yùn)行
??當(dāng)程序在前臺(tái)運(yùn)行時(shí),按下 ctrl+z 可以將程序放入后臺(tái),并且暫停運(yùn)行。
??bg 1 將后臺(tái)暫停的程序切換為運(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è)拷貝的過(guò)程。繼承功能!
??進(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ù),會(huì)將緩沖區(qū)里的數(shù)據(jù)輸出 //exit(0); //直接終止進(jìn)程,會(huì)將緩沖區(qū)里的數(shù)據(jù)輸出 _exit(0); //強(qiáng)制終止進(jìn)程,銷毀緩沖區(qū)中的數(shù)據(jù) } |
??查看僵尸進(jìn)程:ps -aux
??查看系統(tǒng)的環(huán)境變量: env
??修改控制臺(tái)終端的環(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--->先入先出
通過(guò)命令行: mkfifo命令可以直接創(chuàng)建FIFO文件。
無(wú)名管道的FIFO文件不是實(shí)體文件,存在內(nèi)存中的。
文件的方向: 即 fds[0]和讀端相對(duì)應(yīng), fds[1]和寫端相對(duì)應(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è)無(wú)名管道 [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í)無(wú)名管道的通信,刪除指定目錄下的指定后綴的文件。
要求:子進(jìn)程負(fù)責(zé)遍歷文件,父進(jìn)程就負(fù)責(zé)刪除文件。
#include
#include
#include
#include
/*
無(wú)名管道:
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)建無(wú)名管道文件
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ù)一次性寫過(guò)去
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ò)展) 通過(guò)命名管道實(shí)現(xiàn)本地聊天室,一個(gè)終端界面表示一個(gè)用戶。
注明: 就一個(gè).c程序,運(yùn)行一個(gè)就是一個(gè)新的用戶,每個(gè)進(jìn)程之間通過(guò)命名管道通信。
(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)容,所有的用戶都可以顯示出來(lái)。
(6) 通過(guò)一個(gè)文件保存聊天記錄。
-
Linux
+關(guān)注
關(guān)注
87文章
11512瀏覽量
213911 -
編程
+關(guān)注
關(guān)注
88文章
3689瀏覽量
95289 -
進(jìn)程
+關(guān)注
關(guān)注
0文章
207瀏覽量
14291
發(fā)布評(píng)論請(qǐng)先 登錄
Linux系統(tǒng)進(jìn)程管理入門指南

RZ T2H PCIe裸機(jī)程序開(kāi)發(fā)和Linux下的配置介紹

深入Linux進(jìn)程管理:提升效率與穩(wěn)定性的關(guān)鍵方法

一文搞懂Linux進(jìn)程的睡眠和喚醒
Linux應(yīng)用編程的基本概念
Linux用戶身份與進(jìn)程權(quán)限詳解

Linux開(kāi)發(fā)怎么學(xué)?
嵌入式linux開(kāi)發(fā)的基本步驟有哪些?
嵌入式linux開(kāi)發(fā)板怎么操作
嵌入式linux開(kāi)發(fā)板芯片的工作原理
linux開(kāi)發(fā)板與樹(shù)莓派的區(qū)別
linux開(kāi)發(fā)板和單片機(jī)開(kāi)發(fā)的區(qū)別
Linux 驅(qū)動(dòng)開(kāi)發(fā)與應(yīng)用開(kāi)發(fā),你知道多少?

深入探討Linux的進(jìn)程調(diào)度器

評(píng)論