システムコールによるインターフェース呼び出し

はじめに

 前章の内容でデバイスドライバを通してハードウェアを制御する為のインターフェースが、準備できました。本章では、ドライバのインターフェースを通した上位層からの制御について説明します。基本的には7章で説明したsysfsdevtmpfsのファイルに対してシステムコールを呼び出すことで、準備したインターフェースを呼び出します。

システムコールについて

 システムコールとは、Linuxカーネルが提供するプログラムインターフェースで、アプリケーション等のユーザーランド層から、カーネル層の機能にアクセスする為の仕組みです。今までは、Linuxカーネルから呼び出す関数を説明してきましたが、本章はアプリケーションから呼び出す関数の説明になります。ここでの、アプリケーションはprintfを用いて「Hello, world!」を出力するようなプログラムを示しています。

 主要なシステムコールには、以下のようなものがあります。

#include <fcntl.h>
int open(const char *pathname, int flags);

ファイルを開くシステムコールです。第1引数のpathnameのファイルを開き、ファイルディスクリプタを返します。第2引数のflagsには、アクセスモード O_RDONLY, O_WRONLY, O_RDWR等を指定します。

#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);  

ファイルの読み書きをするシステムコールです。第1引数のfdはopenの戻り値であるファイルディスクリプタを、第2引数のbufは読み書きをするバッファーを、第3引数のcountには読み書きをする最大バイト数を指定します。

7.1 sysfs で説明しましたが、近接照度センサドライバは、ltr578_attr_listに登録されている

static DRIVER_ATTR(alstest, S_IWUSR | S_IRUGO, ltr578_show_als,		NULL);

を元にdriver_create_fileを呼び出すことで、

/sys/bus/platform/drivers/als_ps/alstest

を作成していました。

このファイルに対して、openとreadのシステムコールを呼び出すことによって、ファイルが読み込みされた時に呼ばれるコールバック関数として登録していた、ltr578_show_alsが呼び出されます。更に、ltr578_show_alsからltr578_als_readが呼び出され、ltr578_master_recv(client, LTR578_ALS_DATA_0, buf, 0x03)が呼び出され、最終的にはltr578_i2c_read_block(client, addr, buf, count)が呼ばれて、実際のデバイスに存在するALS_DATAレジスタにアクセスできます。

 その他主要なシステムコールに

#include <sys/ioctl.h>
int ioctl(int fd, unsigned long request, ...);  

があります。こちらは、基本的にdevtmpfs上のファイルに対して呼び出すシステムコールであり、単純なread/writeでは実現できない制御を実装できます。miscデバイス登録する関数であるmisc_registerを呼び出す引数として、コールバック関数を登録するfile_operations構造体に以下を入れてました。

static const struct file_operations ltr578_fops = {
	.owner = THIS_MODULE,
	.open = ltr578_open,
	.release = ltr578_release,
	.unlocked_ioctl = ltr578_unlocked_ioctl,
};

この、unlocked_ioctlに指定しているltr578_unlocked_ioctrlに繋がるのが、ioctlシステムコールです。ltr578_unlocked_ioctrlは、以下のように定義されてます。

kernel/mediatek/4.4/drivers/misc/mediatek/sensors-1.0/alsps/ltr578/ltr578.c

static long ltr578_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)

ioctrlシステムコールは例えば以下のように、この内容と合わせて呼び出す必要があります。

ioctl(fd, ALSPS_SET_PS_MODE, arg)

ALSPS_SET_PS_MODEは、カーネルの中では、 kernel/mediatek/4.4/drivers/misc/mediatek/sensors-1.0/hwmon/include/sensors_io.h で定義されていますが、アプリケーションからは参照できないので、同じ値を別ファイルに定義することが基本的に必要になります。

ioctrlシステムコールを呼び出すことで、コールバック関数として登録していた、ltr578_unlocked_ioctlが呼び出され、ALSPS_SET_PS_MODEの値に基づき処理をすることができます。

最後に

 ioctlとdevtmpfsの時に、記載したfile_operations構造体には、これ以外にreadやwriteも指定でき、read/writeシステムコールが呼ばれた際の制御も記載可能です。また、openに登録しているコールバック関数はopenシステムコールが呼ばれた際に呼び出されます。read/writeについては、Linuxのコマンドによるcatやechoによって、処理を呼び出すことが可能です。

 C言語標準でfopenといった、プラットフォームに依存しないファイル制御関数もあります。Linuxではこちらを呼んでも内部的にはopenシステムコールに繋がります。ただ、ioctl等は呼べませんし、sysfsやdevtmpfsにアクセスする時点で、OS依存の処理なので、sysfsやdevtmpfsを制御する際には、Linuxのシステムコールを使うことをお勧めします。

 記載しているシステムコールの詳細、その他のシステムコールについては、 https://linuxjm.osdn.jp/html/LDP_man-pages/man2/syscalls.2.html を参照して下さい。

コメント

タイトルとURLをコピーしました