{"id":102,"date":"2018-02-05T15:13:45","date_gmt":"2018-02-05T23:13:45","guid":{"rendered":"https:\/\/sysprogs.com\/tutorials\/?p=102"},"modified":"2018-02-05T15:26:42","modified_gmt":"2018-02-05T23:26:42","slug":"creating-a-basic-character-device-driver-for-linux","status":"publish","type":"post","link":"https:\/\/sysprogs.com\/VisualKernel\/tutorials\/samples\/chardev\/","title":{"rendered":"Creating a basic character device driver for Linux"},"content":{"rendered":"<p>This tutorial shows how to create a Linux kernel module that will register a simple character device. Character devices support operations like reading\/writing data and sending IOCTL codes. A typical example of a character device would be a COM port. In this tutorial we will create a virtual device that produces a stream of messages like this:<\/p>\n<pre class=\"code \">This is file #X, iteration Y. Z file handle(s) are now active...<\/pre>\n<p>Each time a new user-mode application opens a handle to the device the file number will be increased. Each file instance will have its own iteration counter. The device will produce a one-second delay between the iterations.<\/p>\n<p>Before you begin please follow the\u00a0<a href=\"http:\/\/sysprogs.com\/VisualKernel\/tutorials\/kgdb\/\">basic KGDB tutorial\u00a0<\/a>or one of the other\u00a0<a href=\"http:\/\/sysprogs.com\/VisualKernel\/tutorials\/\">basic tutorials<\/a>\u00a0to ensure that you can create and debug a basic kernel module.<\/p>\n<ol>\n<li>Start Visual Studio. Select File-&gt;New Project-&gt;VisualKernel-&gt;Linux Kernel Module Wizard:<img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/sysprogs.com\/VisualKernel\/legacy_tutorials\/samples\/chardev\/img\/01-newprj.png\" width=\"700\" height=\"394\" \/><\/li>\n<li>Select &#8220;character device&#8221; as the project template on the first page of the wizard:<img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/sysprogs.com\/VisualKernel\/legacy_tutorials\/samples\/chardev\/img\/02-chardev.png\" width=\"696\" height=\"628\" \/><\/li>\n<li>On the next page select the Linux machine you are targeting:<img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/sysprogs.com\/VisualKernel\/legacy_tutorials\/samples\/chardev\/img\/03-target.png\" width=\"696\" height=\"628\" \/><\/li>\n<li>On the third wizard page specify the directory where you want to store the source files:<img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/sysprogs.com\/VisualKernel\/legacy_tutorials\/samples\/chardev\/img\/04-sourcefiles.png\" width=\"696\" height=\"628\" \/><\/li>\n<li>On the last page select the method of connecting to the kernel debugger (e.g. KGDB):<img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/sysprogs.com\/VisualKernel\/legacy_tutorials\/samples\/chardev\/img\/05-kgdb.png\" width=\"696\" height=\"628\" \/><\/li>\n<li>Press &#8220;Finish&#8221; to generate a Visual Studio project. Build it by pressing Ctrl-Shift-B:<img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/sysprogs.com\/VisualKernel\/legacy_tutorials\/samples\/chardev\/img\/06-build.png\" width=\"698\" height=\"562\" \/><\/li>\n<li>Start debugging by pressing F5. VisualKernel will insert the module into the kernel and load the symbols for it. Go to the SSH Session window and click the console button:<img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/sysprogs.com\/VisualKernel\/legacy_tutorials\/samples\/chardev\/img\/07-newssh.png\" width=\"700\" height=\"600\" \/><\/li>\n<li>This will open a multi-tabbed SSH window. Run &#8220;sudo cat \/dev\/&lt;Your project name&gt;&#8221; command:<img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/sysprogs.com\/VisualKernel\/legacy_tutorials\/samples\/chardev\/img\/08-thread1.png\" width=\"692\" height=\"479\" \/><\/li>\n<li>Open a new tab and run the same command in it. Note how the file number will now be 2 and the device will also report that 2 handles are open:<img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/sysprogs.com\/VisualKernel\/legacy_tutorials\/samples\/chardev\/img\/09-thread2.png\" width=\"692\" height=\"479\" \/><\/li>\n<li>Now we will see how the message stream is generated. Go back to Visual Studio and set a breakpoint in the read function:<img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/sysprogs.com\/VisualKernel\/legacy_tutorials\/samples\/chardev\/img\/10-read.png\" width=\"698\" height=\"562\" \/>The call stack shows how the function was invoked as a result of handling the &#8216;read&#8217; syscall. Step through the function by pressing F10 to see how the message is generated.<\/li>\n<li>Our device can produce a one-second delay while handling the read() syscall, so to avoid completely hang the user-mode application that is waiting for us, we are using the\u00a0<strong>msleep_interruptible()<\/strong>\u00a0function. Set a breakpoint on the line returning -EINTR, resume execution, go to the SSH console and press Ctrl-C:<img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/sysprogs.com\/VisualKernel\/legacy_tutorials\/samples\/chardev\/img\/11-interrupt.png\" width=\"698\" height=\"562\" \/>The breakpoint will now hit showing how pressing Ctrl-C resulted in a cancellation of the\u00a0<strong>msleep_interruptible()<\/strong>\u00a0call.<\/li>\n<li>Now we will explore how the handle counter is implemented. Put a breakpoint in the open function and re-run the last command in the SSH console:<img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/sysprogs.com\/VisualKernel\/legacy_tutorials\/samples\/chardev\/img\/12-open.png\" width=\"698\" height=\"562\" \/>You can see how the open syscall invoked our function that allocated a state object and associated it with the file object.<\/li>\n<li>Finally we will explore how the device registration works. Set a breakpoint in the\u00a0<strong>AllocateBasicCharacterDevice()<\/strong>function. Then go to the GDB Session window and reload the module:<img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/sysprogs.com\/VisualKernel\/legacy_tutorials\/samples\/chardev\/img\/13-reload.png\" width=\"700\" height=\"600\" \/><\/li>\n<li>When the breakpoint is hit, step through the function to see the steps required to register the device:<img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/sysprogs.com\/VisualKernel\/legacy_tutorials\/samples\/chardev\/img\/14-register.png\" width=\"698\" height=\"747\" \/><\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>This tutorial shows how to create a Linux kernel module that will register a simple character device. Character devices support<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[30],"tags":[31],"_links":{"self":[{"href":"https:\/\/sysprogs.com\/tutorials\/wp-json\/wp\/v2\/posts\/102"}],"collection":[{"href":"https:\/\/sysprogs.com\/tutorials\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sysprogs.com\/tutorials\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sysprogs.com\/tutorials\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/sysprogs.com\/tutorials\/wp-json\/wp\/v2\/comments?post=102"}],"version-history":[{"count":3,"href":"https:\/\/sysprogs.com\/tutorials\/wp-json\/wp\/v2\/posts\/102\/revisions"}],"predecessor-version":[{"id":111,"href":"https:\/\/sysprogs.com\/tutorials\/wp-json\/wp\/v2\/posts\/102\/revisions\/111"}],"wp:attachment":[{"href":"https:\/\/sysprogs.com\/tutorials\/wp-json\/wp\/v2\/media?parent=102"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sysprogs.com\/tutorials\/wp-json\/wp\/v2\/categories?post=102"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sysprogs.com\/tutorials\/wp-json\/wp\/v2\/tags?post=102"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}