日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁 > 嵌入式 > 嵌入式云IOT技術(shù)圈
[導(dǎo)讀]上節(jié)我們分享了Linux進(jìn)程間通信的其中兩種方式:管道、消息隊(duì)列,文章如下: Linux進(jìn)程間通信(上)之管道、消息隊(duì)列實(shí)踐 這節(jié)我們就來分享一下Linux的另外兩種進(jìn)程間通信的方式:信號(hào)、信號(hào)量。 1、信號(hào) 我們使用過windows的都知道,當(dāng)一個(gè)程序被卡死的時(shí)候不

上節(jié)我們分享了Linux進(jìn)程通信的其中兩種方式:管道、消息隊(duì)列,文章如下:

Linux進(jìn)程間通信(上)之管道、消息隊(duì)列實(shí)踐

這節(jié)我們就來分享一下Linux的另外兩種進(jìn)程間通信的方式:信號(hào)、信號(hào)量。

1、信號(hào)

我們使用過windows的都知道,當(dāng)一個(gè)程序被卡死的時(shí)候不管怎樣都沒反應(yīng),這樣我們就可以打開任務(wù)管理器直接強(qiáng)制性的結(jié)束這個(gè)進(jìn)程,這個(gè)方法的實(shí)現(xiàn)就是和Linux上通過生成信號(hào)和捕獲信號(hào)來實(shí)現(xiàn)相似的,運(yùn)行過程中進(jìn)程捕獲到這些信號(hào)做出相應(yīng)的操作使最終被終止。

信號(hào)的主要來源是分為兩部分,一部分是硬件來源,一部分是軟件來源;進(jìn)程在實(shí)際中可以用三種方式來響應(yīng)一個(gè)信號(hào):一是忽略信號(hào),不對(duì)信號(hào)做任何操作,其中有兩個(gè)信號(hào)是不能別忽略的分別是SIGKILL和SIGSTOP。二是捕捉信號(hào),定義信號(hào)處理函數(shù),當(dāng)信號(hào)來到時(shí)做出響應(yīng)的處理。三是執(zhí)行缺省操作,Linux對(duì)每種信號(hào)都規(guī)定了默認(rèn)操作。注意,進(jìn)程對(duì)實(shí)時(shí)信號(hào)的缺省反應(yīng)是立即終止。

發(fā)送信號(hào)的函數(shù)有很多,主要使用的有:kill()、raise()、abort()、alarm()。

先來熟悉下kill函數(shù),進(jìn)程可以通過kill()函數(shù)向包括它本身在內(nèi)的其它進(jìn)程發(fā)送一個(gè)信號(hào),如果程序沒有發(fā)送這個(gè)信號(hào)的權(quán)限,對(duì)kill函數(shù)的調(diào)用將會(huì)失敗,失敗的原因通常是由于目標(biāo)進(jìn)程由另一個(gè)用戶所擁有。

kill函數(shù)的原型為:

#include<sys/types.h>
#include<signal.h>
int kill(pid_t pid,int sig);

它的作用是把信號(hào)sig發(fā)送給進(jìn)程號(hào)為pid的進(jìn)程,成功時(shí)返回0。kill調(diào)用失敗返回-1,調(diào)用失敗通常有三大原因:

  • 1、給定的信號(hào)無效
  • 2、發(fā)送權(quán)限不夠
  • 3、目標(biāo)進(jìn)程不存在

還有一個(gè)非常重要的函數(shù),信號(hào)處理signal函數(shù)。程序可以用signal函數(shù)來處理指定的信號(hào),主要通過恢復(fù)和忽略默認(rèn)行為來操作。signal函數(shù)原型如下:

typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);

我們來看一個(gè)例程了解一下signal函數(shù)。signal.c

#include <stdio.h>
#include <signal.h>
#include <unistd.h>

//函數(shù)ouch對(duì)通過參數(shù)sig傳遞進(jìn)來的信號(hào)作出響應(yīng)。
void ouch(int sig)
{
 printf("signal %d\n", sig);
 //恢復(fù)終端中斷信號(hào)SIGINT的默認(rèn)行為
 (void) signal(SIGINT, SIG_DFL);
}
int main()
{
  //改變終端中斷信號(hào)SIGINT的默認(rèn)行為,使之執(zhí)行ouch函數(shù)
  (void) signal(SIGINT, ouch);
 
  while(1)
  {
   printf("Hello World!\n");
   sleep(1); 
  }
 return 0;
}

運(yùn)行結(jié)果:


可以看出當(dāng)我按下ctrl+c的時(shí)候并不會(huì)退出,只有當(dāng)再次按下ctrl+c的時(shí)候才會(huì)退出。造成的原因是因?yàn)镾IGINT的默認(rèn)行為被signal函數(shù)改變了,當(dāng)進(jìn)程接受到信號(hào)SIGINT時(shí),它就去調(diào)用函數(shù)ouch去處理,注意ouch函數(shù)把信號(hào)SIGINT的處理方式改變成默認(rèn)的方式,所以當(dāng)你再按一次ctrl+c時(shí),進(jìn)程就像之前那樣被終止了。

下面是幾種常見的信號(hào):

  • SIGHUP :從終端上發(fā)出的結(jié)束信號(hào)
  • SIGINT :來自鍵盤的中斷信號(hào) ( ctrl + c )
  • SIGKILL :該信號(hào)結(jié)束接收信號(hào)的進(jìn)程
  • SIGTERM:kill 命令發(fā)出的信號(hào)
  • SIGCHLD:標(biāo)識(shí)子進(jìn)程停止或結(jié)束的信號(hào)
  • SIGSTOP:來自鍵盤 ( ctrl + z ) 或調(diào)試程序的停止執(zhí)行信號(hào)。

信號(hào)發(fā)送主要函數(shù)有kill和raise。上面我們知道kill函數(shù)的用法也清楚kill函數(shù)是可以向自身發(fā)送信號(hào)和其它進(jìn)程發(fā)送信號(hào),raise與之不同的是只可以向本身發(fā)送信號(hào)。

通過raise函數(shù)向自身發(fā)送數(shù)據(jù),使子進(jìn)程暫停通過測(cè)試如下: raise.c

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

int main()
{
  pid_t pid;
  int ret;
  if((pid=fork())<0)
  {
   printf("Fork error\n");
   exit(1);
  }
  //子進(jìn)程
  if(pid==0)
  {
   //在子進(jìn)程中使用raise()函數(shù)發(fā)出SIGSTOP信號(hào),使子進(jìn)程暫停
   printf("I am child pid:%d.I am waiting for any signal\n",getpid());
   raise(SIGSTOP);
   printf("I am child pid:%d.I am killed by progress:%d\n",getpid(),getppid());
   exit(0);
  }
  //父進(jìn)程
  else  
  {
   sleep(2);  
   //在父進(jìn)程中收集子進(jìn)程發(fā)出的信號(hào),并調(diào)用kill()函數(shù)進(jìn)行相應(yīng)的操作
   if((waitpid(pid,NULL,WNOHANG))==0) 
   { 
  //若pid指向的子進(jìn)程沒有退出,則返回0,且父進(jìn)程不阻塞,繼續(xù)執(zhí)行下邊的語句
    if((ret=kill(pid,SIGKILL))==0)
    {
     printf("I am parent pid:%d.I am kill %d\n",getpid(),pid);
    }
   }
   //等待子進(jìn)程退出,否則就一直阻塞
   waitpid(pid,NULL,0);
   exit(0);
  }
}

當(dāng)調(diào)用raise的時(shí)候子進(jìn)程就會(huì)暫停:

信號(hào)是對(duì)終端機(jī)的一種模擬,也是一種異步通信方式。


2、信號(hào)量

主要作為進(jìn)程間,以及同一進(jìn)程不同線程之間的同步手段。信號(hào)量是用來解決進(jìn)程之間的同步與互斥問題的一種進(jìn)程之間的通信機(jī)制,包括一個(gè)稱為信號(hào)量的變量和在該信號(hào)量下等待資源的進(jìn)程等待隊(duì)列,以及對(duì)信號(hào)量進(jìn)行的兩個(gè)原子操作。信號(hào)量對(duì)應(yīng)于某一種資源,取一個(gè)非負(fù)的整形值。信號(hào)量的值是指當(dāng)前可用的資源數(shù)量。

由于信號(hào)量只有兩種操作,一種是等待信號(hào),另一種是發(fā)送信號(hào)。即P和V,它們的行為如下:

  • P(sv):如果sv的值大于零,就給它減1;如果它的值為零,就掛起該進(jìn)程的執(zhí)行。
  • V(sv):如果有其他進(jìn)程因等待sv而被掛起,就讓它恢復(fù)運(yùn)行,如果沒有進(jìn)程因等待sv而掛起,就給它加1。

Linux特別提供了一組信號(hào)量接口來對(duì)信號(hào)操作,它們不只是局限的針對(duì)二進(jìn)制信號(hào)量,下面我們來對(duì)每個(gè)函數(shù)介紹,需要注意的是這些函數(shù)都是用來成對(duì)組的信號(hào)量值進(jìn)行操作的。

2.1、semget函數(shù)

它的作用是創(chuàng)建一個(gè)新信號(hào)量或取得一個(gè)已有信號(hào)量。

int semget(key_t key, int nsems, int semflg); 

第一個(gè)參數(shù)是key整數(shù)型,不相關(guān)的進(jìn)程可以通過它訪問一個(gè)信號(hào)量,它代表程序可能要使用的某個(gè)資源,程序?qū)λ行盘?hào)量的訪問都是間接的,先通過調(diào)用semget函數(shù)并提供一個(gè)鍵,再由系統(tǒng)生成一個(gè)相應(yīng)的信號(hào)標(biāo)識(shí)符(semget函數(shù)的返回值),只有semget函數(shù)才直接使用信號(hào)量鍵,所有其他的信號(hào)量函數(shù)使用由semget函數(shù)返回的信號(hào)量標(biāo)識(shí)符。如果多個(gè)程序使用相同的key值,key將負(fù)責(zé)協(xié)調(diào)工作。

第二個(gè)參數(shù)是制定需要的信號(hào)數(shù)量,通常情況下為1。

第三個(gè)參數(shù)是一組標(biāo)志位,當(dāng)想要當(dāng)信號(hào)量不存在時(shí)創(chuàng)建一個(gè)新的信號(hào)量,可以和值IPC_CREAT做按位或操作。設(shè)置了IPC_CREAT標(biāo)志后,即使給出的鍵是一個(gè)已有信號(hào)量的鍵,也不會(huì)產(chǎn)生錯(cuò)誤。而IPC_CREAT | IPC_EXCL則可以創(chuàng)建一個(gè)新的,唯一的信號(hào)量,如果信號(hào)量已存在,返回一個(gè)錯(cuò)誤。

semget函數(shù)成功返回一個(gè)相應(yīng)信號(hào)標(biāo)識(shí)符(非零),失敗返回-1。

2.2、semop函數(shù)

它的作用是改變信號(hào)量的值。

int semop(int semid, struct sembuf *sops, unsigned nsops);

sops是一個(gè)指針,它指向這樣一個(gè)數(shù)組:元素用來描述對(duì)semid代表的信號(hào)量集合中第幾個(gè)信號(hào)進(jìn)行怎么樣的操作。nops規(guī)定該數(shù)組中操作的數(shù)量。

semop函數(shù)返回0表示成功,返回-1表示失敗。

2.3、semctl函數(shù)

該函數(shù)用來直接控制信號(hào)量信息。

int semctl(int semid, int semnum, int cmd, …);

semget并不會(huì)初始化每個(gè)信號(hào)量的值,這個(gè)初始化必須通過SETVAL命令或SETALL命令調(diào)用semctl來完成。

例程:semctl.c

#include <stdio.h>
#include <linux/sem.h>
#define NUMS 10  

int get_sem_val(int sid,int semnum)//取得當(dāng)前信號(hào)量
{  
  return(semctl(sid,semnum,GETVAL,0));  
}  

int main(void)
{  
  int I ;
  int sem_id;  
  int pid;  
  int ret;  
  struct sembuf sem_op;//信號(hào)集結(jié)構(gòu)
  union semun sem_val;//信號(hào)量數(shù)值

  //建立信號(hào)量集,其中只有一個(gè)信號(hào)量
  sem_id = semget(IPC_PRIVATE,1,IPC_CREAT|0600);
  //IPC_PRIVATE私有,只有本用戶使用,如果為正整數(shù),則為公共的;1為信號(hào)集的數(shù)量;
  if (sem_id==-1)
  {  
    printf("create sem error!\n");  
    exit(1);      
  }  
  printf("create %d sem success!\n",sem_id);      
  //信號(hào)量初始化
  sem_val.val=1;  
  //設(shè)置信號(hào)量,0為第一個(gè)信號(hào)量,1為第二個(gè)信號(hào)量,...以此類推;SETVAL表示設(shè)置
   ret = semctl(sem_id,0,SETVAL,sem_val);  
  if (ret < 0){  
    printf("initlize sem error!\n");  
    exit(1);      
   }  
   //創(chuàng)建進(jìn)程
  pid = fork();  
  if (pid < 0)
  {  
    printf("fork error!\n");  
    exit(1);             
  }  
  else if(pid == 0)
  {
      //一個(gè)子進(jìn)程,使用者
      for ( i=0;i<NUMS;i++)
      {  
        sem_op.sem_num=0;  
        sem_op.sem_op=-1;  
        sem_op.sem_flg=0;  
        semop(sem_id,&sem_op,1);//操作信號(hào)量,每次-1                  
        printf("%d 使用者: %d\n",i,get_sem_val(sem_id,0));  
      }       
  }  
  else
  {
      //父進(jìn)程,制造者
     for (i=0;i<NUMS;i++)
     {  
          sem_op.sem_num=0;  
          sem_op.sem_op=1;  
          sem_op.sem_flg=0;  
          semop(sem_id,&sem_op,1);//操作信號(hào)量,每次+1                   
          printf("%d 制造者: %d\n",i,get_sem_val(sem_id,0));  
     }       
 }  
 exit(0);  
}

運(yùn)行結(jié)果:

信號(hào)量的出現(xiàn)就是保證資源在一個(gè)時(shí)刻只能有一個(gè)進(jìn)程(線程),所以例子當(dāng)中只有制造者在制造(+1操作)過程中,使用者這個(gè)進(jìn)程是無法隨sem_id進(jìn)行操作的。也就是說信號(hào)量是協(xié)調(diào)進(jìn)程對(duì)共享資源操作的,起到了類似互斥鎖的作用,但卻比鎖擁有更強(qiáng)大的功能。

往期精彩

Linux進(jìn)程通信(上)之管道、消息隊(duì)列實(shí)踐

C語言三劍客之《C陷阱與缺陷》一書精華提煉

C語言三劍客之《C專家編程》一書精華提煉

【為宏正名】99%人都不知道的"##"里用法

【Linux系統(tǒng)編程】可重入和不可重入函數(shù)

覺得本次分享的文章對(duì)您有幫助,隨手點(diǎn)[在看]并轉(zhuǎn)發(fā)分享,也是對(duì)我的支持。

免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問題,請(qǐng)聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅(qū)動(dòng)電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: 驅(qū)動(dòng)電源

在工業(yè)自動(dòng)化蓬勃發(fā)展的當(dāng)下,工業(yè)電機(jī)作為核心動(dòng)力設(shè)備,其驅(qū)動(dòng)電源的性能直接關(guān)系到整個(gè)系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動(dòng)勢(shì)抑制與過流保護(hù)是驅(qū)動(dòng)電源設(shè)計(jì)中至關(guān)重要的兩個(gè)環(huán)節(jié),集成化方案的設(shè)計(jì)成為提升電機(jī)驅(qū)動(dòng)性能的關(guān)鍵。

關(guān)鍵字: 工業(yè)電機(jī) 驅(qū)動(dòng)電源

LED 驅(qū)動(dòng)電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個(gè)照明設(shè)備的使用壽命。然而,在實(shí)際應(yīng)用中,LED 驅(qū)動(dòng)電源易損壞的問題卻十分常見,不僅增加了維護(hù)成本,還影響了用戶體驗(yàn)。要解決這一問題,需從設(shè)計(jì)、生...

關(guān)鍵字: 驅(qū)動(dòng)電源 照明系統(tǒng) 散熱

根據(jù)LED驅(qū)動(dòng)電源的公式,電感內(nèi)電流波動(dòng)大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關(guān)鍵字: LED 設(shè)計(jì) 驅(qū)動(dòng)電源

電動(dòng)汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產(chǎn)業(yè)的重要發(fā)展方向。電動(dòng)汽車的核心技術(shù)之一是電機(jī)驅(qū)動(dòng)控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機(jī)驅(qū)動(dòng)系統(tǒng)中的關(guān)鍵元件,其性能直接影響到電動(dòng)汽車的動(dòng)力性能和...

關(guān)鍵字: 電動(dòng)汽車 新能源 驅(qū)動(dòng)電源

在現(xiàn)代城市建設(shè)中,街道及停車場(chǎng)照明作為基礎(chǔ)設(shè)施的重要組成部分,其質(zhì)量和效率直接關(guān)系到城市的公共安全、居民生活質(zhì)量和能源利用效率。隨著科技的進(jìn)步,高亮度白光發(fā)光二極管(LED)因其獨(dú)特的優(yōu)勢(shì)逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關(guān)鍵字: 發(fā)光二極管 驅(qū)動(dòng)電源 LED

LED通用照明設(shè)計(jì)工程師會(huì)遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關(guān)鍵字: LED 驅(qū)動(dòng)電源 功率因數(shù)校正

在LED照明技術(shù)日益普及的今天,LED驅(qū)動(dòng)電源的電磁干擾(EMI)問題成為了一個(gè)不可忽視的挑戰(zhàn)。電磁干擾不僅會(huì)影響LED燈具的正常工作,還可能對(duì)周圍電子設(shè)備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關(guān)鍵字: LED照明技術(shù) 電磁干擾 驅(qū)動(dòng)電源

開關(guān)電源具有效率高的特性,而且開關(guān)電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機(jī)重量也有所下降,所以,現(xiàn)在的LED驅(qū)動(dòng)電源

關(guān)鍵字: LED 驅(qū)動(dòng)電源 開關(guān)電源

LED驅(qū)動(dòng)電源是把電源供應(yīng)轉(zhuǎn)換為特定的電壓電流以驅(qū)動(dòng)LED發(fā)光的電壓轉(zhuǎn)換器,通常情況下:LED驅(qū)動(dòng)電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: LED 隧道燈 驅(qū)動(dòng)電源
關(guān)閉