0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

getcharの入力待ちにCtrl+Cで割り込みたい

Last updated at Posted at 2024-07-12

(備忘録)(7/12:ご指摘に対応)

やりたかったこと

getchar()で入力待ちループをしているときに、Ctrl+Cが押されたことを取得しこれをもとにターミナルに画面表示をしたかった
(そういう要望であったため、Ctrl+C以外を使用するなどは不可)

はじめに作ったソース

signal()でSIGINT(Ctrl+C 押下時のシグナル)を設定


// シグナルハンドラ処理
static void ctrl_c_event( int sig )
{
	// Ctrl+C押下を取得し、これをもとに画面表示
	test_disp(0xff); // 画面表示処理
}

// メイン
int main(int argc, char *argv[])
{
    char input;

    signal( SIGINT, ctrl_c_event );

	// ループで標準入力を取得 入力をもとに画面表示を行う処理
	while(1){
       input = getchar();
       test_disp(input); // 画面表示処理
    }

	return 0;
}

解決…?

これで問題ないかと思っていたが、シグナルハンドラ内でのprintfは推奨されない らしい。
参考にしたqiitaの記事
また、signalを使用するのも推奨されない らしい

対策

ので、対策として以下のように変更した。

Ctrl+C 押下時のシグナルハンドラでフラグを有効化

// シグナルハンドラ処理
static volatile sig_atomic_t ctrl_c_flag;
static void ctrl_c_event( int sig )
{
	ctrl_c_flag = 1; // フラグを有効化
}

getchar()をread()に変更し、read()のコールをselect()によって制御するように変更
read()のタイムアウト後の処理でフラグのチェックを行い、フラグが有効であればCtrl+Cが押下されたことを通知
また、signalをsigactionに変更

// メイン
int main(int argc, char *argv[])
{
    char input;

	static struct sigaction sig_ctrl_c;	// Ctrl+C通知用

	// sigaction初期化
	sigemptyset(&sig_ctrl_c.sa_mask);		// シグナルマスクをクリア
	sig_ctrl_c.sa_handler = ctrl_c_event;	// Ctrl+C通知関数を登録

	// シグナルハンドラ登録
	sigaction( SIGINT, &sig_ctrl_c, NULL);

	while(1){
		FD_ZERO(&fd_group);					// グループを初期化
		FD_SET(STDIN_FILENO, &fd_group);	// 標準入力をグループに追加

		if( select(STDIN_FILENO + 1, &fd_group, NULL, NULL, &timeout) == -1) return 0;

		// 入力を監視/処理
		if (FD_ISSET(STDIN_FILENO, &fd_group)) {
			// 標準入力からデータを読み込み
			if (read(STDIN_FILENO, &data, sizeof(data)) > 0) {
				test_disp(input);		// 画面表示処理
			}
		}

		// Ctrl+C イベント取得
		if(ctrlc_event_flag){
			test_disp(0xff); 			// 画面表示処理
			ctrl_c_flag = false;		// フラグをクリア
		}

		usleep(10 * 1000);	// 負荷軽減(10ミリ秒)
	}

	return 0;
}
0
0
7

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?