目錄
前言
一,有名管道通信
1 .概念
2 .創(chuàng)建有名管道
實(shí)例代碼如下:
二、信號(hào)通信
1 .概念
2 .用戶進(jìn)程對(duì)信號(hào)的響應(yīng)方式
3. 用戶進(jìn)程對(duì)常用信號(hào)的缺省操作
4. 信號(hào)處理流程
5. 信號(hào)相關(guān)函數(shù)(系統(tǒng)調(diào)用)
?5.1 kill - 給指定進(jìn)程發(fā)送信號(hào)
實(shí)例代碼如下:?
5.2 raise() --給當(dāng)前進(jìn)程發(fā)送信號(hào) ?
實(shí)例代碼如下:?
5.3 alarm() 在進(jìn)程中設(shè)置定時(shí)器(鬧鐘) ?
實(shí)例代碼如下:?
5.4 pause() 使進(jìn)程掛起 ?
?實(shí)例代碼如下:
5.5 signal 注冊(cè)信號(hào) ?
實(shí)例代碼如下:?
總結(jié)
前言
上篇博客對(duì)C/C++進(jìn)程的中部分進(jìn)行了詳細(xì)講解,本篇博客將繼續(xù)講解和補(bǔ)充關(guān)于線程的知識(shí)點(diǎn)。
一,有名管道通信
1 .概念
1.由于無(wú)名管道只能用于具有親緣關(guān)系的進(jìn)程之間,這就限制了無(wú)名管道的使用范圍。
2.而有名管道可以使互不相關(guān)的兩個(gè)進(jìn)程互相通信。有名管道可以通過(guò)路徑名來(lái)指出,并且在文件系統(tǒng)中可見(jiàn)
3.進(jìn)程通過(guò)文件IO來(lái)操作有名管道
2 .創(chuàng)建有名管道
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
//參數(shù)1 ---- 管道的名稱
//參數(shù)2 ---- 管道的權(quán)限
//返回值 -----成功:0,失?。?1例如:
int main(int argc ,char **argv)
? ? {? ? ? ? if(argc != 2){
? ? ? ? ? ? fprintf(stderr,"Usage: %s <fifoname>\n",argv[0]);
? ? ? ? ? ? exit(1);
? ? ? ? }? ? ? ? //創(chuàng)建有名管道
? ? ? ? if(mkfifo(argv[1],0666) < 0){ ? //管道權(quán)限= 0666 & ~umusk
? ? ? ? ? ? perror("mkfifo");
? ? ? ? ? ? exit(1);
? ? ? ? }? ? ? ? return 0;
? ? }
實(shí)例代碼如下:
//從管道讀10個(gè)整數(shù),然后排序,并打印
int main(int argc ,char **argv)
{
int fd;
int a[10],i,j,flag;
if(argc != 2){
fprintf(stderr,"Usage: %s <fifoname>\n",argv[0]);
exit(1);
}
//判斷管道文件是否存在,如果不存在則創(chuàng)建,存在則直接打開(kāi)
if(access(argv[1],F_OK)){
//創(chuàng)建有名管道
if(mkfifo(argv[1],0666) < 0){ //管道權(quán)限= 0666 & ~umusk
perror("mkfifo");
exit(1);
}
}
//打開(kāi)管道
if((fd = open(argv[1],O_RDWR)) < 0){
perror("open");
exit(1);
}
//從管道中讀10個(gè)整數(shù)
if(read(fd,a,sizeof(a)) < 0){
perror("read");
exit(1);
}
//排序
for(i = 0; i < 9; i++){
flag = 1;
for(j = 0; j < 9-i; j++)
if(a[j] > a[j+1]){
a[j] = a[j] + a[j+1];
a[j+1] = a[j] - a[j+1];
a[j] = a[j] - a[j+1];
flag = 0;
}
if(flag)
break;
}
for(i = 0; i < 10; i++){
printf("%d ",a[i]);
fflush(stdout);
sleep(1);
}
printf("\n");
close(fd);
return 0;
}
//從鍵盤(pán)輸入10個(gè)整數(shù),并寫(xiě)入管道
int main(int argc ,char **argv)
{
int fd;
int a[10],i;
if(argc != 2){
fprintf(stderr,"Usage: %s <fifoname>\n",argv[0]);
exit(1);
}
//判斷管道文件是否存在,如果不存在則創(chuàng)建,存在則直接打開(kāi)
if(access(argv[1],F_OK)){
//創(chuàng)建有名管道
if(mkfifo(argv[1],0666) < 0){ //管道權(quán)限= 0666 & ~umusk
perror("mkfifo");
exit(1);
}
}
//打開(kāi)管道
if((fd = open(argv[1],O_RDWR)) < 0){
perror("open");
exit(1);
}
//鍵盤(pán)輸入10個(gè)整數(shù)
printf("請(qǐng)輸入10個(gè)整數(shù):");
for(i = 0; i < 10; i++){
scanf("%d",&a[i]);
}
//向管道中寫(xiě)10個(gè)整數(shù)
write(fd,a,sizeof(a));
close(fd);
return 0;
}
二、信號(hào)通信
1 .概念
信號(hào)是在軟件層次上對(duì)中斷機(jī)制的一種模擬,是一種異步通信方式
信號(hào)可以直接進(jìn)行用戶空間進(jìn)程和內(nèi)核進(jìn)程之間的交互,內(nèi)核進(jìn)程也可以利用它來(lái)通知用戶空間進(jìn)程發(fā)生了哪些系統(tǒng)事件。
如果該進(jìn)程當(dāng)前并未處于執(zhí)行態(tài),則該信號(hào)就由內(nèi)核保存起來(lái),直到該進(jìn)程恢復(fù)執(zhí)行再傳遞給它;如果一個(gè)信號(hào)被進(jìn)程設(shè)置為阻塞,則該信號(hào)的傳遞被延遲,直到其阻塞被取消時(shí)才被傳遞給進(jìn)程
2 .用戶進(jìn)程對(duì)信號(hào)的響應(yīng)方式
(1)忽略信號(hào):
?? ?對(duì)信號(hào)不做任何處理,但是有兩個(gè)信號(hào)不能忽略:即SIGKILL及SIGSTOP。
(2)捕捉信號(hào):
?? ?定義信號(hào)處理函數(shù),當(dāng)信號(hào)發(fā)生時(shí),執(zhí)行相應(yīng)的處理函數(shù)。
(3)執(zhí)行缺省操作:
?? ?Linux對(duì)每種信號(hào)都規(guī)定了默認(rèn)操作//查看linux系統(tǒng)中的信號(hào)---kill
peter@ubuntu:~/2308/proc/day03_code$ kill -l
?1) SIGHUP ? ? ? 2) SIGINT ? ? ? 3) SIGQUIT ? ? ?4) SIGILL ? ? ? 5) SIGTRAP
?6) SIGABRT ? ? ?7) SIGBUS ? ? ? 8) SIGFPE ? ? ? 9) SIGKILL ? ? 10) SIGUSR1
11) SIGSEGV ? ? 12) SIGUSR2 ? ? 13) SIGPIPE ? ? 14) SIGALRM ? ? 15) SIGTERM
16) SIGSTKFLT ? 17) SIGCHLD ? ? 18) SIGCONT ? ? 19) SIGSTOP ? ? 20) SIGTSTP
21) SIGTTIN ? ? 22) SIGTTOU ? ? 23) SIGURG ? ? ?24) SIGXCPU ? ? 25) SIGXFSZ
26) SIGVTALRM ? 27) SIGPROF ? ? 28) SIGWINCH ? ?29) SIGIO ? ? ? 30) SIGPWR
31) SIGSYS ? ? ?34) SIGRTMIN ? ?35) SIGRTMIN+1 ?36) SIGRTMIN+2 ?37) SIGRTMIN+3
38) SIGRTMIN+4 ?39) SIGRTMIN+5 ?40) SIGRTMIN+6 ?41) SIGRTMIN+7 ?42) SIGRTMIN+8
43) SIGRTMIN+9 ?44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 ?56) SIGRTMAX-8 ?57) SIGRTMAX-7
58) SIGRTMAX-6 ?59) SIGRTMAX-5 ?60) SIGRTMAX-4 ?61) SIGRTMAX-3 ?62) SIGRTMAX-2
63) SIGRTMAX-1 ?64) SIGRTMAX
3. 用戶進(jìn)程對(duì)常用信號(hào)的缺省操作
信號(hào)名 | 含義 | 默認(rèn)操作 |
---|---|---|
SIGHUP | 該信號(hào)在用戶終端連接(正?;蚍钦?結(jié)束時(shí)發(fā)出,通常是在終端的控? ? 制進(jìn)程結(jié)束時(shí),通知同一會(huì)話內(nèi)的各個(gè)作業(yè)與控制終端不再關(guān)聯(lián)。?? ??? ??? ? |
終止 |
SIGINT | 該信號(hào)在用戶鍵入INTR字符(通常是Ctrl-C)時(shí)發(fā)出,終端驅(qū)動(dòng)程序發(fā)送? ? ? ? ? ? ? ? ?? 此信號(hào)并送到前臺(tái)進(jìn)程中的每一個(gè)進(jìn)程。?? ??? ??? ??? ? |
終止 |
SIGQUIT | 該信號(hào)和SIGINT類似,但由QUIT字符(通常是Ctrl-\)來(lái)控制。 | 終止 |
SIGILL | 該信號(hào)在一個(gè)進(jìn)程企圖執(zhí)行一條非法指令時(shí)(可執(zhí)行文件本身出現(xiàn)錯(cuò)誤,? ? ? ? ? ? ? ? ? ? ? 或者試圖執(zhí)行數(shù)據(jù)段、堆棧溢出時(shí))發(fā)出。?? ? |
終止 |
SIGFPE | 該信號(hào)在發(fā)生致命的算術(shù)運(yùn)算錯(cuò)誤時(shí)發(fā)出。這里不僅包括浮點(diǎn)運(yùn)算錯(cuò)誤,? ? ? ? ? ? ? ? ? ? ?還包括溢出及除數(shù)為0等其它所有的算術(shù)的錯(cuò)誤。?? ? |
終止 |
SIGKILL | 該信號(hào)用來(lái)立即結(jié)束程序的運(yùn)行,并且不能被阻塞、處理和忽略。 | 終止 |
SIGALRM | 該信號(hào)當(dāng)一個(gè)定時(shí)器到時(shí)的時(shí)候發(fā)出。 | 終止 |
SIGSTOP | 該信號(hào)用于暫停一個(gè)進(jìn)程,且不能被阻塞、處理或忽略。 | 暫停進(jìn)程 |
SIGTSTP | 該信號(hào)用于暫停交互進(jìn)程,用戶可鍵入SUSP字符(通常是Ctrl-Z)發(fā)出這個(gè)信號(hào)。 | 暫停進(jìn)程 |
SIGCHLD | 子進(jìn)程改變狀態(tài)時(shí),父進(jìn)程會(huì)收到這個(gè)信號(hào) | 忽略 |
SIGABORT | 該信號(hào)用于結(jié)束進(jìn)程 | 終止 |
4. 信號(hào)處理流程
?
5. 信號(hào)相關(guān)函數(shù)(系統(tǒng)調(diào)用)
?5.1 kill - 給指定進(jìn)程發(fā)送信號(hào)
#include <sys/types.h>
? ? #include <signal.h>
? ? int kill(pid_t pid, int sig);
? ? //參數(shù)1 ?-----信號(hào)發(fā)送的目標(biāo)進(jìn)程的ID
? ? ?? ??? ??? ? 參數(shù)1取值分四種
? ? ?? ??? ??? ? pid > 0 ,給進(jìn)程號(hào)為pid的進(jìn)程發(fā)送信號(hào)
? ? ?? ??? ??? ? pid = 0 , 給當(dāng)前進(jìn)程組中每一個(gè)進(jìn)程發(fā)送信號(hào)
? ? ?? ??? ??? ? pid = -1, 發(fā)送給進(jìn)程表中所有的進(jìn)程
? ? ?? ??? ??? ? pid < -1, 給指定進(jìn)程組中的每一個(gè)進(jìn)程發(fā)送信號(hào),該進(jìn)程組的ID為-pid
? ? //參數(shù)2 ?-----要發(fā)送的信號(hào)
? ? //返回值----成功:0,失?。?1
實(shí)例代碼如下:?
int main(int argc,char **argv)
{
#if 1
pid_t pid;
if(argc != 2){
fprintf(stderr,"Usage: %s <pid>\n",argv[0]);
exit(1);
}
pid = atoi(argv[1]); //atoi將字符串轉(zhuǎn)為整數(shù)
if(kill(pid,SIGKILL) < 0){
perror("kill");
exit(1);
}
#else
pid_t pid1,pid2;
int i;
if((pid1 = fork()) < 0){
perror("fork");
exit(1);
}else if(!pid1){ //子進(jìn)程1
for(i = 0; ; i++){
printf("pid = %d\n",getpid());
sleep(1);
}
}else{
if((pid2 = fork()) < 0){
perror("fork");
exit(1);
}else if(!pid2){ //子進(jìn)程2
for(i = 0; ; i++){
printf("pid = %d\n",getpid());
sleep(1);
}
}else{ //父進(jìn)程
for(i = 0; ; i++){
printf("pid = %d\n",getpid());
sleep(1);
if(i == 5)
//kill(0,SIGKILL); //0--給進(jìn)程組中每一個(gè)進(jìn)程發(fā)送信號(hào)
kill(pid2,SIGKILL); //給pid2發(fā)送信號(hào)
}
}
}
#endif
return 0;
}
5.2 raise() --給當(dāng)前進(jìn)程發(fā)送信號(hào) ?
#include <signal.h>
int raise(int sig);
//參數(shù) ----信號(hào)
//返回值----成功:0,失?。?1
實(shí)例代碼如下:?
int main(void)
{
int i;
for(i = 0; ; i++){
printf("pid = %d\n",getpid());
sleep(1);
if(i == 7)
raise(SIGKILL);
}
return 0;
}
5.3 alarm() 在進(jìn)程中設(shè)置定時(shí)器(鬧鐘) ?
#include <unistd.h>
unsigned int alarm(unsigned int seconds);
//參數(shù) ---- 要定時(shí)的秒數(shù)
//返回值 ----如果第一次調(diào)用該函數(shù),返回值為0,
?? ??? ??? ?如果調(diào)用之前已經(jīng)設(shè)置了定時(shí)器,則返回上次定時(shí)剩余的秒數(shù)
實(shí)例代碼如下:?
int main(void)
{
int i,ret;
ret = alarm(20); // 從該語(yǔ)句開(kāi)始計(jì)時(shí),7秒之后發(fā)送SIGALRM信號(hào)給當(dāng)前進(jìn)程
printf("ret = %d\n",ret);
for(i = 0; ; i++){
printf("pid = %d,i = %d\n",getpid(),i);
sleep(1);
if(i == 7){
ret = alarm(5);
printf("ret = %d\n",ret);
}
}
return 0;
}
5.4 pause() 使進(jìn)程掛起 ?
int pause(void);
//使進(jìn)程掛起 ,直到進(jìn)程收到任意一個(gè)信號(hào)則返回。
?實(shí)例代碼如下:
//信號(hào)處理函數(shù)
void fun(int signo)
{
int i;
for(i = 0; i < 3; i++){
printf(GREEN "正在吃飯\n"NONE);
sleep(1);
}
}
int main(void)
{
int i,j;
//注冊(cè)信號(hào)SIGALRM
signal(SIGINT,fun);
for(i = 0; ; i++){
pause(); //使進(jìn)程掛起,直到收到信號(hào)為止
for(j = 0; j < 5; j++){
printf("正在睡覺(jué)\n");
sleep(1);
}
}
return 0;
}
5.5 signal 注冊(cè)信號(hào) ?
#include <signal.h>
typedef void (*sighandler_t)(int); ?//定義函數(shù)指針類型名稱
sighandler_t signal(int signum, sighandler_t handler);
//參數(shù)1 ---- 要注冊(cè)的信號(hào)
//參數(shù)2 ---- 信號(hào)的響應(yīng)方式:
?? ??? ??? ??? ?SIG_IGN ? ----- 忽略信號(hào)
?? ??? ??? ??? ?SIG_DFL ? ----- 對(duì)信號(hào)進(jìn)行缺省操作
?? ??? ?信號(hào)處理函數(shù)的指針 ? ?----- 捕捉信號(hào),當(dāng)收到信號(hào),則會(huì)執(zhí)行信號(hào)處理函數(shù)
?? ??? ?void xxx_fun(int)
?? ??? ?{
?? ??? ?
?? ??? ?}
//返回值 ----成功:信號(hào)處理函數(shù)指針,失敗:SIG_ERR
實(shí)例代碼如下:?
//信號(hào)處理函數(shù)
void eat(int signo)
{
int i;
for(i = 0; i < 3; i++){
printf(GREEN "正在吃飯\n"NONE);
sleep(1);
}
}
int main(void)
{
int i;
//注冊(cè)信號(hào)SIGALRM
signal(SIGALRM,eat);
for(i = 0; ; i++){
if(i % 8 == 0){
alarm(8); // 從該語(yǔ)句開(kāi)始計(jì)時(shí),7秒之后發(fā)送SIGALRM信號(hào)給當(dāng)前進(jìn)程
printf("開(kāi)始睡覺(jué),設(shè)置鬧鐘\n");
}
printf("正在睡覺(jué)......\n");
sleep(1);
}
return 0;
}
總結(jié)
? ? ? ? 本篇文章針對(duì)進(jìn)程進(jìn)行最后的超詳細(xì)講解和補(bǔ)充,希望能夠幫到大家!
? ? ? ? 以后還會(huì)給大家展現(xiàn)更多關(guān)于嵌入式和C語(yǔ)言的其他重要的基礎(chǔ)知識(shí),感謝大家支持懶大王!文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-715576.html
? ? ? ?希望這篇博客能給各位朋友們帶來(lái)幫助,最后懶大王請(qǐng)來(lái)過(guò)的朋友們留下你們寶貴的三連以及關(guān)注,感謝你們!文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-715576.html
到了這里,關(guān)于C/C++進(jìn)程超詳細(xì)詳解【下部分】(系統(tǒng)性學(xué)習(xí)day8)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!