婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識庫 > Linux被中斷的系統(tǒng)如何調(diào)用詳解

Linux被中斷的系統(tǒng)如何調(diào)用詳解

熱門標簽:江西外呼系統(tǒng) 蘭州ai電銷機器人招商 新邵電銷機器人企業(yè) 外呼系統(tǒng)打哪顯哪 新科美甲店地圖標注 高德地圖標注論壇 北海市地圖標注app 湖北ai智能電銷機器人 AI電銷機器人 源碼

前言

慢系統(tǒng)調(diào)用,指的是可能永遠無法返回,從而使進程永遠阻塞的系統(tǒng)調(diào)用,比如無客戶連接時的accept、無輸入時的read都屬于慢速系統(tǒng)調(diào)用。

在Linux中,當(dāng)阻塞于某個慢系統(tǒng)調(diào)用的進程捕獲一個信號,則該系統(tǒng)調(diào)用就會被中斷,轉(zhuǎn)而執(zhí)行信號處理函數(shù),這就是被中斷的系統(tǒng)調(diào)用。

然而,當(dāng)信號處理函數(shù)返回時,有可能發(fā)生以下的情況:

  • 如果信號處理函數(shù)是用signal注冊的,系統(tǒng)調(diào)用會自動重啟,函數(shù)不會返回
  • 如果信號處理函數(shù)是用sigaction注冊的
    • 默認情況下,系統(tǒng)調(diào)用不會自動重啟,函數(shù)將返回失敗,同時errno被置為EINTR
    • 只有中斷信號的SA_RESTART標志有效時,系統(tǒng)調(diào)用才會自動重啟

下面我們編寫代碼,分別驗證上述幾種情形,其中系統(tǒng)調(diào)用選擇read,中斷信號選擇SIGALRM,中斷信號由alarm產(chǎn)生。

使用signal

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

void handler(int s)
{
  printf("read is interrupt by signal handler\n");
  return;
}

int main()
{
  char buf[10];
  int nread = 0;

  signal(SIGALRM, handler);
  alarm(2);

  printf("read start\n");
  nread = read(STDIN_FILENO, buf, sizeof(buf));
  printf("read return\n");

  if ((nread < 0) && (errno == EINTR))
  {
    printf("read return failed, errno is EINTR\n");
  }

  return 0;
}

使用sigaction + 默認情況

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

void handler(int s)
{
  printf("read is interrupt by signal handler\n");
  return;
}

int main()
{
  char buf[10];
  int nread = 0;
  struct sigaction act;

  sigemptyset(&act.sa_mask);
  act.sa_handler = handler;
  act.sa_flags = 0; //不給SIGALRM信號設(shè)置SA_RESTART標志,使用sigaction的默認處理方式
  //act.sa_flag |= SA_INTERRUPT; //SA_INTERRUPT是sigaction的默認處理方式,即不自動重啟被中斷的系統(tǒng)調(diào)用
  //實際上,不管act.sa_flags值為多少,只要不設(shè)置SA_RESTART,sigaction都是按SA_INTERRUPT處理的

  sigaction(SIGALRM, &act, NULL);
  alarm(2);

  printf("read start\n");
  nread = read(STDIN_FILENO, buf, sizeof(buf));
  printf("read return\n");

  if ((nread < 0) && (errno == EINTR))
  {
    printf("read return failed, errno is EINTR\n");
  }

  return 0;
}


使用sigaction + 指定SA_RESTART標志

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

void handler(int s)
{
  printf("read is interrupt by signal handler\n");
  return;
}

int main()
{
  char buf[10];
  int nread = 0;
  struct sigaction act;

  sigemptyset(&act.sa_mask);
  act.sa_handler = handler;
  act.sa_flags = 0;
  act.sa_flags |= SA_RESTART; //給SIGALRM信號設(shè)置SA_RESTART標志

  sigaction(SIGALRM, &act, NULL);
  alarm(2);

  printf("read start\n");
  nread = read(STDIN_FILENO, buf, sizeof(buf));
  printf("read return\n");

  if ((nread < 0) && (errno == EINTR))
  {
    printf("read return failed, errno is EINTR\n");
  }

  return 0;
}


由于對被中斷系統(tǒng)調(diào)用處理方式的差異性,因此對應(yīng)用程序來說,與被中斷的系統(tǒng)調(diào)用相關(guān)的問題是:

  • 應(yīng)用程序無法保證總是知道信號處理函數(shù)的注冊方式,以及是否設(shè)置了SA_RESTART標志
  • 可移植的代碼必須顯式處理關(guān)鍵函數(shù)的出錯返回,當(dāng)函數(shù)出錯且errno等于EINTR時,可以根據(jù)實際需求進行相應(yīng)處理,比如重啟該函數(shù)
int nread = read(fd, buf, 1024);

if (nread < 0)
{
  if (errno == EINTR)
  {
    //read被中斷,其實不應(yīng)該算作失敗,可以根據(jù)實際需求進行處理,比如重寫調(diào)用read,也可以忽略它
  }
  else
  {
    //read真正的讀錯誤
  }
}

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,謝謝大家對腳本之家的支持。

標簽:黔東 阿克蘇 黃石 南陽 大理 池州 海南 自貢

巨人網(wǎng)絡(luò)通訊聲明:本文標題《Linux被中斷的系統(tǒng)如何調(diào)用詳解》,本文關(guān)鍵詞  Linux,被,中斷,的,系統(tǒng),如何,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《Linux被中斷的系統(tǒng)如何調(diào)用詳解》相關(guān)的同類信息!
  • 本頁收集關(guān)于Linux被中斷的系統(tǒng)如何調(diào)用詳解的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    主站蜘蛛池模板: 河津市| 枣庄市| 宿迁市| 遵化市| 罗江县| 漳州市| 松原市| 广南县| 牟定县| 民乐县| 剑阁县| 上饶县| 繁昌县| 合作市| 鸡东县| 和林格尔县| 台江县| 苍梧县| 三河市| 五台县| 蒙阴县| 石门县| 洛浦县| 花莲市| 繁峙县| 古浪县| 丹寨县| 河南省| 交城县| 新巴尔虎右旗| 固镇县| 施甸县| 利川市| 搜索| 呼玛县| 阜新市| 涞源县| 同江市| 和龙市| 新沂市| 离岛区|