7

現在、Linuxのデバイスドライバーを勉強中です。デバイスファイルを開く方法に行き詰まりましたか?

今まで得たもの...通常のファイルを開く簡単なコードを考えてみましょう..

#incldue<stdio.h>
int main() {
   FILE fp;
   char buffer[20];
   fp = fopen(/home/yoggi/foo.txt, "r");
   fread(buffer, 5, 1, fp);
}

上記のプログラムでは、c-library 関数である fopen() はシステム コールopen()のラッパー関数であり、インターンはVFS 層関数で sys_open() または file_open() を呼び出します。Linux は多数のファイル システムをサポートしているため、仮想ファイル システムは、そのファイルを開く実際のファイル システム ハンドラに制御を移します。

1) How does virtual file system(VFS) get to know on which file system the 
   underline file resides?
2) How does it then calls the file_open or open function of that particular
   filesystem to open file.

デバイス ドライバーの場合、同様のことが起こります。単純なデバイス ドライバーを想定します。

#include <linux/module.h>
// othher includes... 
static dev_t first; // Global variable for the first device number 
static struct cdev c_dev; // Global variable for the character device structure
static struct class *cl; // Global variable for the device class
static int my_open(struct inode *i, struct file *f)
{
   printk(KERN_INFO "Driver: open()\n");
   return 0;
} 
static ssize_t my_read(struct file *f, char __user *buf, size_t len, loff_t *off)
{
   printk(KERN_INFO "Driver: read()\n");
   return 0;
}
struct file_operations pugs_fops =
{
 .owner = THIS_MODULE,
 .open = my_open,
 .read = my_read,
};

static int __init ofcd_init(void) /* Constructor */
{
  printk(KERN_INFO "Namaskar: ofcd registered");
  if (alloc_chrdev_region(&first, 0, 1, "Shweta") < 0)
  {
    return -1;
  }
  if ((cl = class_create(THIS_MODULE, "chardrv")) == NULL)
  {
     unregister_chrdev_region(first, 1);
     return -1;
 }
 if (device_create(cl, NULL, first, NULL, "mynull") == NULL)
 {
    class_destroy(cl);
    unregister_chrdev_region(first, 1);
    return -1;
 }
   cdev_init(&c_dev, &pugs_fops);
 if (cdev_add(&c_dev, first, 1) == -1)
 {
   device_destroy(cl, first);
   class_destroy(cl);
   unregister_chrdev_region(first, 1);
   return -1;
 }
  return 0;
}

static void __exit ofcd_exit(void) /* Destructor */
{
 cdev_del(&c_dev);
 device_destroy(cl, first);
 class_destroy(cl);
 unregister_chrdev_region(first, 1);
 printk(KERN_INFO "Alvida: ofcd unregistered");
} 
module_init(ofcd_init);
module_exit(ofcd_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Anil Kumar Pugalia <email_at_sarika-pugs_dot_com>");
MODULE_DESCRIPTION("Our First Character Driver");

まず、デバイスにメジャー マイナー番号を割り当てます。デバイスファイルの範囲を登録し、デバイスファイル操作をデバイスドライバー機能にリンクします。

私が得られなかった用語のいくつかは..

1) What does actually cdev_add() do? in terms of registering a device to the 
   kernel.
2) Registering a device to the kernel means?
3) How does a open(/dev/mynull, O_RONLY); called on a device file actually calls 
   the open function of driver which is mapped while initializing the device 
   by calling routine cdev_init(&c_dev, &pugs_fops); ?
4

1 に答える 1

11

1) 仮想ファイル システム (VFS) は、下線ファイルが存在するファイル システムをどのように認識しますか?

開こうとしているファイルをフルパス名 (または現在の作業ディレクトリ) で指定する必要があります。
したがって、このディレクトリ パスを逆方向にたどると、最初に一致したマウント ポイント (最も深いパス) が、マウントされたファイル システム、ファイル システムのタイプ、およびデバイスを提供します。

各ファイルシステムは、マウント時にこの情報を提供し、マウント テーブルに保存されます。
コマンドを使用して、この (現在の状態) 情報を表示できますmount

2) 次に、その特定のファイルシステムの file_open または open 関数を呼び出してファイルを開く方法。

ファイルシステムが認識されるopsと、その fs の構造が取得され、open()エントリポイントを呼び出すことができます。

1) cdev_add() は実際に何をしますか? デバイスをカーネルに登録するという点で。

ドライバーの登録 ( cdev_init()char デバイスなど) は、opsドライバーが実行できる機能のエントリポイントをリストするドライバーの構造をインストールします。
cdev_add()ドライバーがそのcharデバイスタイプの特定のインスタンスを制御できることをカーネルに通知します。そのデバイス インスタンスには、デバイス名を/devドライバーの状態情報に関連付けるマイナー番号が割り当てられます。
char 以外のデバイス タイプ (ネットワーク デバイスやプラットフォーム (バス) デバイスなど) は、別のサブシステムに属し、別の登録手順を使用することに注意してください。

2) デバイスをカーネルに登録するということは?

そのデバイスへのアクセスが有効になりました。

3) open(/dev/mynull, O_RONLY); はどのようにしますか? デバイスファイルで呼び出されると、実際には、ルーチン cdev_init(&c_dev, &pugs_fops) を呼び出してデバイスを初期化する際にマップされるドライバーの open 関数が呼び出されます。?

ドライバーのinit()ルーチンは、ドライバーが読み込まれるときに 1 回だけ呼び出す必要があります。このルーチンは、デバイスのすべてのインスタンスの存在と動作状態を調べる必要があります。割り込みライン、DMA チャネル、I/O ポート、メモリ空間などのリソースを取得する必要があります。ドライバーは、そのops構造をカーネルに登録します。ドライバーは、デバイスの各インスタンスをカーネルに登録します。

open()ユーザー空間での呼び出しは、C ライブラリによって処理されます。/devデバイス名は、デバイスのメジャー番号 ( tty や audio など、どのデバイス サブシステムまたはクラスが要求処理する必要があるかを識別する) とマイナー番号 (使用するデバイス ドライバーと、デバイスのどのインスタンスにアクセスするかを識別する) に変換されます。 )。プロセッサはスーパバイザ モードに切り替えられ、カーネル ドライバのルーチンを呼び出すことができます。このルーチンは、ドライバの構造open()から取得されます。ops構造の詳細opsについては、この他の回答を参照してください。

于 2013-01-25T00:37:56.827 に答える