LinuxにおけるCtrl+Cの仕組み

この記事は、IPFactory Advent Calendar 2022 の23日目の記事です。

https://qiita.com/advent-calendar/2022/ipfactory


# はじめに

Linuxをよく使用している人なら、お世話になったことも多いであろう「Ctrl+C」。
システムレベルではどんなことが起こっているのでしょうか。



# Ctrl+Cの正体

プロセスの実行中にCtrl+Cを入力すると、そのプロセスを終了させることができます。
Ctrl+Cは、どんな働きをするように設定されているのでしょうか。

sttyコマンドを-aオプション付きで実行してみます。

```
$ stty -a
speed 38400 baud; rows 30; columns 120; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; swtch = <undef>; start = ^Q;
stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; discard = ^O; min = 1; time = 0;
-parenb -parodd -cmspar cs8 -hupcl -cstopb cread -clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc -ixany -imaxbel -iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke -flusho -extproc
```

２行目、`intr = ^C`に注目してください。`^C`はCtrl+Cを意味しています。
`intr`はinterruptの略で、割り込みを意味しています。

このことから、Ctrl+Cを押すと割り込みの処理が発生することがわかりました。

端末でプロセスが実行中にキーボードでCtrl+Cが入力されると、割り込みの命令が送られてプロセスは終了します。



# Linuxの成り立ち

もう少し詳しくCrtl+Cの仕組みを見ていく前に、Linuxの成り立ちを大まかに説明します。

Linuxはファイルシステムとプロセス、ストリーム*で形成されています。
*（ここでいうストリームという用語は、本記事の参考文献が独自で使用している表現なので、一般的にこのような表現が使用されているわけではないです）

- ファイル
    ファイルというものを一口で言い切るのは難しいですが、ここでは
    - 何らかのデータを保持するもの
    - 付帯情報がついているもの
    - 名前（パス）で指定できるもの
   
    のような特徴を持つものをファイルと呼びます。

- プロセス
    プロセスとは、動作中のプログラムのことです。
    プログラムは、ファイルのような形態で存在しているデータのことも含む言葉です。

    シェルで`ps -ef`と入力すると、現在自分のコンピュータに存在するプロセスがすべて表示されます。試しに私のコンピュータで実行してみます。
```
ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 09:33 ?        00:00:00 /init
root         7     1  0 09:33 ?        00:00:00 /init
root         8     7  0 09:33 ?        00:00:00 /init
doradebi     9     8  0 09:33 pts/0    00:00:00 -bash
doradebi    66     9  0 09:33 pts/0    00:00:00 ps -ef
```
   このように、コンピュータ上では常にいろいろなプロセスが動いていることがわかります。

- ストリーム
    ストリームは、データをやり取りするためのバイト列が流れる通り道のことです。

    例えばプロセスがファイルにアクセスしたいときは、プロセスがファイルにつながるストリームを作ってもらうようにカーネルに頼みます。そうしてストリームを作ってもらったら、ストリームを操作してファイルの中身を取り出します。

    ファイルとプロセス間、プロセスとプロセス間、ハードウェアとファイル間のような、どんなもの同士のやりとりでもバイト列の流れと考えられるものであれば、どんなものでもストリームであるかのように扱うことができます。


#### 補足
- カーネル
 「Linux」は、一般的にはOSのことだと思われがちですが、厳密にはLinuxという単語はカーネルだけを指しています。カーネル(karnel)とはOSの核にあたるもので、ただ1つのプログラムで構成されており、コンピュータを構成するすべてのハードウェアとソフトウェアを管理しているものです。

- シェル
シェルは、ユーザからの命令を解釈して実行するプログラムです。Linuxにユーザがログインすると、シェルは起動されます。
普段私たちユーザがターミナルでコマンドを実行するとき、コマンドラインに`$`や`%`などが表示されていると思いますが、それはシェルが端末からの入力を認識できる状態になっている証拠です。


# もう少し詳しく

では早速、Ctrl+Cが押されてからプロセスが終了されるまでのもう少し詳細な流れを追ってみましょう。

1. 端末でプロセスが動作中の時にキーボードでCtrl+Cが押される
2. その情報がカーネル内の端末ドライバに送られ、そこで端末ドライバはCtrl+Cを割り込みと認識する
3. 端末ドライバでSIGINTという割り込みを示すシグナルが生成され、端末で動作中のプロセスに送られる
4. プロセスがデフォルトの動作にしたがって終了する

しかしここで気になるのは、Linux上では常にいくつかのプロセスが動いているということです。
端末ドライバは、どのようにしていくつかのプロセスの中から端末で動いているプロセスを見つけているのでしょうか。

。。。端末で動いているプロセスなのに、端末ドライバがそのプロセスの内容を認識できない？不自然に感じた人がいるかもしれませんが、当然なことなのです。

これは、ノートパソコンをプロジェクターにつないでスライドを映すことと似たようなことです。この時、プロジェクターはパソコンから送られてきたデータを随時画像として出力しているだけで、プロジェクターがスライド全体のデータを保存しているわけではありませんよね。
端末とプロセスも例に挙げたプロジェクターとパソコンの関係と同じで、端末はシェルが実行したプロセスの内容まで認識しているわけではないのです。

少し話が逸れてしまいましたが、実はシェルが、プロセスを起動するたびに現在端末で動いているプロセスを端末に教えています。端末ドライバはそれを頼りに端末で動いているプロセスを見つけることができているのです。



# おわりに

いかがだったでしょうか。
私は今年の春から情報技術について学び始めて、せっかくならwslで導入したLinuxの仕組みについて知りたいということで本記事の参考にさせていただいた本を読みました。
普段何気なく使用しているPCですが、操作する人間にとっては1つの処理でも、裏ではこのようにいろいろな処理が行われているということが実感できて、勉強になりました。
拙い部分も多かったでしょうが、この記事でLinuxの仕組みについて少しでも興味を持ってくれたら幸いです。



### 参考文献

ふつうのLinuxプログラミング 第2版 Linuxの仕組みから学べるgccプログラミングの王道

---
この記事は、IPFactory Advent Calendar 2022 の23日目の記事です。
昨日は [riiriirii](https://qiita.com/riiriirii) さんの記事でした。明日は [Ogin0pan](https://qiita.com/Ogin0pan) さんの記事です。