3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

組込プログラミング:排他制御

Last updated at Posted at 2023-02-28

■排他制御とは

前回、ファームウエアの中には「タスク」という一連の処理を繰り返し行うプログラムがたくさんあって、それらは並行して動く、ということを書きました。このようなタスクの並行処理環境で次に必要になってくるのが「排他制御」です。「他」を「排する」というくらいなので、現実世界で言うとカラオケルームで誰かが使っていたら他の人は排される(待たされる)みたいなものでしょうか。タスクを使ってプログラミングを進めていると、タスクAがある資源(メモリ上の情報)を読み書きする一連の処理の間は、タスクBにはその資源の読み書きをしないでほしい、というケースが出てくると思います。

もう少し具体的に例を挙げましょう。

タスクA:
void task_a()
{
	int i;
	
	for (i = 0; i < 10; i ++) {
		printf(%d\r\n", i);
	}
}
タスクB:
void task_b()
{
	int i;
	
	for (i = 0; i < 10; i ++) {
		printf("%c\r\n", 'a'+i);
	}
}

これらが並列に動くとどうなるでしょうか。
(※注)
実際にこれらをタスクとして実行すると、ただループを実行してタスクが終了してしまいます。簡略化のため話題の他の要素は省略していますのでご注意ください。

なんとなく、

0
a
1
b
2
c
...

のように互い違いに出力されるかもね、くらいのイメージは持てるかと思います。実際はもっとひどくて、

0a

1
b
c

...

のように、文字とCRの間やCRとLFの間でタスクが切り替わる可能性もあります。ですから、例えば少なくとも「文字\r\n」までは一気に表示したいのであれば、

タスクA:
void task_a()
{
	int i;
	
	for (i = 0; i < 10; i ++) {
		排他開始
		printf(%d\r\n", i);
		排他終了
	}
}
タスクB:
void task_b()
{
	int i;
	
	for (i = 0; i < 10; i ++) {
		排他開始
		printf("%c\r\n", 'a'+i);
		排他終了
	}
}

のように排他制御APIを呼び出すことになります。
(応用問題として、0~9、a~jまでそれぞれを一気に表示したいのであれば、どこで排他開始、終了APIを呼び出すと良いかわかりますか?)

■名前:セマフォとミューテックス

排他制御するものの名前として以下の2つがあります。
〇セマフォ
冒頭に書いたカラオケルームがたとえば10部屋持っていたとしたら、最初の10組はすぐに入れますがそれ以降は空き待ちになります。どこかが空いたら待ち行列の先頭の組が入れます。このように、資源が複数あるものの制御を行うものをセマフォと言います。もともとは進行か停止を指示する鉄道などの手旗信号が語源のようです。

〇ミューテックス
こっちはカラオケルームが1部屋ある場合です。つまり「空きかどうか」だけを表現するもので、資源数が1のセマフォはミューテックスと同じ、と言えます(厳密には機能的な違いもあるのですが、ここでは省略します)。
語源はmutual exclusion:相互排他から来ているようです。

iTRON OSでは普通排他制御に資源数1のセマフォを使います(そのため、これ以降ここでは排他制御するもののことをセマフォと呼びます)。排他開始APIはwai_sem()、排他終了APIはsig_sem()です。動的生成に対応しているiTRON OSの場合、目的に応じてcre_sem()にて任意の数だけセマフォを生成して使用します。動的生成に対応していないiTRON OSの場合は添付のコンフィグレータなどのツールで静的生成します。

正直、最低限iTRON OSにはタスクとセマフォだけ用意されていれば、あとのタスク間メッセージ通信やメモリ確保などの仕組みは最悪自分で書けます。セマフォはそれぐらいタスクと並んでOSの根幹となる仕組みなのです。特定の資源のみを排他制御できる便利な機能ですが、実はその使用には細心の注意が必要です。今回はセマフォの概要説明で終わってしまったので、その話は次回に回します。

■今日の閑話

セマフォは名前の使い方が独特な感じがします。語源が手旗信号というところから、排他開始はwait semaphoreだからwai_sem()、排他終了はsignal semaphoreだからsig_sem()まではなんとなくイメージできます。でも私がこの会社に入ったとき、先達が作ったOSではsemP()、semV()という名前がついていました。何のP、Vか諸説あるようですが、結局は手旗信号関連のオランダ語のようです。完全にP/Vに慣れた後でwai/sigの世界に入ったとき、またどっちが開始でどっちが終了か覚えるのにややしばらくかかりました...

Cente:
https://www.cente.jp/

お問合せはこちら:
https://www.cente.jp/otoiawase/

3
3
0

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
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?