Linuxで中断されたシステムを呼び出す方法

Linuxで中断されたシステムを呼び出す方法

序文

低速システム コールとは、決して戻らない可能性があり、プロセスを永久にブロックするシステム コールを指します。たとえば、クライアント接続がない場合の accept と入力がない場合の read は、どちらも低速システム コールです。

Linux では、遅いシステム コールでブロックされたプロセスがシグナルをキャプチャすると、システム コールが中断され、代わりにシグナル処理関数が実行されます。これが中断されたシステム コールです。

ただし、信号処理機能が復帰すると、次のような状況が発生する可能性があります。

  • シグナル処理関数が signal に登録されている場合、システムコールは自動的に再開され、関数は戻りません。
  • 信号処理機能がsigactionに登録されている場合
    • デフォルトでは、システムコールは自動的に再開されず、関数は失敗を返し、errnoはEINTRに設定されます。
    • システムコールは、割り込み信号の SA_RESTART フラグが有効な場合にのみ自動的に再開されます。

次に、システムコールが読み取りを選択し、割り込み信号が SIGALRM を選択し、アラームによって割り込み信号が生成される上記の状況をそれぞれ検証するコードを記述します。

信号の使用

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

void ハンドラ(int s)
{
  printf("読み取りはシグナルハンドラによって中断されました\n");
  戻る;
}

int メイン()
{
  char バッファ[10];
  int nread = 0;

  シグナル(SIGALRM、ハンドラ);
  警報(2);

  printf("読み取り開始\n");
  nread = read(STDIN_FILENO、buf、sizeof(buf));
  printf("読み取り戻り\n");

  ((nread < 0) && (errno == EINTR))の場合
  {
    printf("読み取り戻りに失敗しました。errno は EINTR\n");
  }

  0を返します。
} 

sigaction + default を使用する

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

void ハンドラ(int s)
{
  printf("読み取りはシグナルハンドラによって中断されました\n");
  戻る;
}

int メイン()
{
  char バッファ[10];
  int nread = 0;
  構造体sigaction行為;

  sigemptyset(&act.sa_mask);
  act.sa_handler = ハンドラー;
  act.sa_flags = 0; //SIGALRM シグナルの SA_RESTART フラグを設定せず、sigaction のデフォルトの処理方法を使用します //act.sa_flag |= SA_INTERRUPT; //SA_INTERRUPT は sigaction のデフォルトの処理方法であり、中断されたシステム コールを自動的に再開しません。 //実際、act.sa_flags の値が何であっても、SA_RESTART が設定されていない限り、sigaction は SA_INTERRUPT に従って処理されます sigaction(SIGALRM, &act, NULL);
  警報(2);

  printf("読み取り開始\n");
  nread = read(STDIN_FILENO、buf、sizeof(buf));
  printf("読み取り戻り\n");

  ((nread < 0) && (errno == EINTR))の場合
  {
    printf("読み取り戻りに失敗しました。errno は EINTR\n");
  }

  0を返します。
} 


sigactionを使用し、SA_RESTARTフラグを指定する

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

void ハンドラ(int s)
{
  printf("読み取りはシグナルハンドラによって中断されました\n");
  戻る;
}

int メイン()
{
  char バッファ[10];
  int nread = 0;
  構造体sigaction行為;

  sigemptyset(&act.sa_mask);
  act.sa_handler = ハンドラー;
  act.sa_flags = 0;
  act.sa_flags |= SA_RESTART; //SIGALRM シグナルの SA_RESTART フラグを設定します。sigaction(SIGALRM, &act, NULL);
  警報(2);

  printf("読み取り開始\n");
  nread = read(STDIN_FILENO、buf、sizeof(buf));
  printf("読み取り戻り\n");

  ((nread < 0) && (errno == EINTR))の場合
  {
    printf("読み取り戻りに失敗しました。errno は EINTR\n");
  }

  0を返します。
} 


中断されたシステム コールの処理方法の違いにより、アプリケーションの中断されたシステム コールに関連する問題は次のとおりです。

  • アプリケーションは、シグナル ハンドラーがどのように登録されたか、および SA_RESTART フラグが設定されているかどうかを常に認識できるとは限りません。
  • 移植可能なコードでは、主要な関数からのエラー戻りを明示的に処理する必要があります。関数が失敗し、errno が EINTR に等しい場合は、関数を再起動するなど、それに応じて処理できます。
int nread = read(fd, buf, 1024);

(nread < 0)の場合
{
  (エラー番号 == EINTR)の場合
  {
    // 読み取りが中断されましたが、これは失敗とはみなされません。読み取りの呼び出しを書き換えたり、無視したりするなど、実際のニーズに応じて処理できます。}
  それ以外
  {
    //実際の読み取りエラーを読み取る}
}

要約する

以上がこの記事の全内容です。この記事の内容が皆様の勉強や仕事に何らかの参考学習価値をもたらすことを願います。123WORDPRESS.COM をご愛顧いただき、誠にありがとうございます。

以下もご興味があるかもしれません:
  • Linux でプロセスのシステム コールとパラメータを取得する (トラブルシューティングのケース)
  • Linux C におけるライブラリ関数とシステムコールの違いの詳細な分析
  • Linux システムコールと標準ライブラリコールの違いの詳細な分析
  • Linux システムコールを実装する 3 つの方法
  • Linux システムコールに基づく方法 - getrlimit() および setrlimit() 関数
  • Linuxシステムコール原理の詳細な説明
  • Linux カーネル デバイス ドライバー システム コールに関する注意事項

<<:  MySQL 構成 SSL マスタースレーブ レプリケーション

>>:  React antdはフォームの動的な増減を実現します

推薦する

Windows 7 での MySQL 8.0.18 の導入とインストールのチュートリアル

1. 事前準備 (windows7+mysql-8.0.18-winx64) 1. ダウンロードアド...

Nginx コンテンツ キャッシュと共通パラメータ設定の詳細

使用シナリオ:プロジェクトのページでは、頻繁に変更されず、個別のカスタマイズも伴わない大量のデータを...

ubuntu20.04 上の CLion2020.1.3 での ROS のインストールと設定の詳細な説明

1. CLionをダウンロード、インストール、アクティベートするオンラインで提供されるチュートリアル...

MySQL Null は 5 つの問題を引き起こす可能性があります (すべて致命的)

目次1. カウントデータが失われる解決2. 明確なデータ損失3.データ損失を選択解決4. Nullポ...

画面なしで無線ネットワークに接続しているときに Raspberry Pi の IP アドレスを見つける方法

あなたがlinuxerだと仮定すると、 windowserだとは想定しません。Windows ユーザ...

JavaScript 文字列の一般的なメソッドの詳細な説明

目次1. キャラクター文法パラメータ索引戻り値2. 連結文法パラメータ文字列2 [, …文字列N]戻...

Vue-Routerのインストールプロセスと原理の詳細

目次1. フロントエンドルーティングの実装原則2. vue-Routerの基本的な使い方2.1. イ...

mysql 5.7.20 win64 のインストールと設定方法

mysql-5.7.20-winx64.zipインストール手順のないインストール パッケージ: ht...

WeChatミニプログラムユーザー認証による携帯電話番号の取得(getPhoneNumber)

序文ミニプログラムには、ユーザーを取得するための非常に便利な API があり、getPhoneNum...

Vue3 でマークダウン エディター コンポーネントを使用する方法

目次インストールコンポーネントのインポート基本的な使い方保存したマークダウンまたは HTML テキス...

よく使用される入力テキストボックスの内容は自動的に垂直方向に中央揃えされ、クリックするとデフォルトのプロンプトテキストは空になります。

3つの機能: 1. コンテンツの垂直方向の自動中央揃え2. デフォルトのプロンプトテキストは灰色で表...

MySQLのinnodb_data_file_pathパラメータを変更する際の注意事項

序文innodb_data_file_path は、innodb テーブルスペース ファイルを指定す...

Reactの3つの主要属性における状態の使用の詳細な説明

目次クラスコンポーネント機能コンポーネントsetStateの落とし穴React では多くの場所でデー...

MySQLトリガーの詳細な説明と簡単な例

MySQLトリガーの簡単な例文法CREATE TRIGGER <トリガー名> -- トリ...

Linux環境でタイムゾーンを設定できない問題を解決

Linuxでタイムゾーンを変更する場合、常に変更することはできませんAsia/Shanghai に変...