Author Topic: Topic donated. No longer about learning to write a driver for fun and with ease  (Read 1831 times)

0 Members and 1 Guest are viewing this topic.

Online RoGeorgeTopic starter

  • Super Contributor
  • ***
  • Posts: 6791
  • Country: ro
- How easy?
- This easy!

The 'hello_drv.c' file:
Code: [Select]
#include <linux/module.h>
#include <linux/init.h>

int __init my_init(void)
{
printk("hello_drv - Hello from the kernel!\n");
return 0;
}

void __exit my_exit(void)
{
printk("hello_drv - Bye, bye, driver unloaded.\n");
}

MODULE_LICENSE("GPL");
MODULE_AUTHOR("RoGeorge");
MODULE_DESCRIPTION("The Hello World of a Loadable Kernel Module");

module_init(my_init);
module_exit(my_exit);

The 'Makefile':
Code: [Select]
obj-m += hello_drv.o

all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean




- How?
- From a terminal, install the build tools, make the .ko module then load/unload your driver into the Linux kernel!  8)
('hello_drv.c', 'Makefile' and a compiled 'hello_drv.ko' are in the zip archive attached at the end of this post)
Code: [Select]
/*
 * # as seen in the [url]https://www.youtube.com/watch?v=2-vKcbfa0bc[/url]
 *
 * Linux Driver Workshop at Kieler Linuxtage (english)
 * Johannes 4GNU_Linux
 * by Johannes Roith, 2023-09-15
 *
 * sudo apt install build-essential
 * sudo apt install linux-headers-$(uname -r)
 *
 * make
 *
 * sudo dmesg
 * sudo insmod ./hello_drv.ko # loads the driver module into the Linux kernel
 * # sudo modprobe ./hello_drv.ko # loads the driver including its dependencies
 * sudo dmesg # observe the message in the kernel log '[timestamp] hello_drv - Hello from the kernel!'
 *
 * lsmod | grep hello_drv
 *
 * sudo rmmod ./hello_drv.ko
 * sudo dmesg # observe the message '[timestamp] hello_drv - Bye, bye, driver unloaded.
 *
 * modinfo ./hello_drv.ko
 *
 * make clean
 */

Interested for more than just the Hello World?  See the full workshop (1.5 hours):
Linux Driver Workshop at Kieler Linuxtage (english)
Johannes 4GNU_Linux

https://youtu.be/2-vKcbfa0bc

or the playlist 'Let's code a Linux Driver' from the same YT channel:
https://www.youtube.com/playlist?list=PLCGpd0Do5-I3b5TtyqeF1UdyD4C-S-dMa
« Last Edit: September 20, 2023, 02:56:21 pm by RoGeorge »
 
The following users thanked this post: pqass

Offline janoc

  • Super Contributor
  • ***
  • Posts: 3885
  • Country: de
Re: Hrrmmm. Learn to code a linux driver you must. It's easy. Hmm.
« Reply #1 on: September 16, 2023, 10:00:28 pm »
That may sound a bit pedantic but what you have there is not a driver of any kind, only a Linux kernel module (for the uninitiated - sort of a kernel plugin). Most drivers are modules these days but not every module is a driver and not every driver is/can be a module.

Try to write a driver e.g. for a new block device or some USB device, then the "It's easy" would have more relevance  ;)



 
The following users thanked this post: MarginallyStable, SiliconWizard

Offline magic

  • Super Contributor
  • ***
  • Posts: 7240
  • Country: pl
Re: Hrrmmm. Learn to code a linux driver you must. It's easy. Hmm.
« Reply #2 on: September 17, 2023, 07:46:41 am »
The use of "code" as a verb is an instant giveaway that you are dealing with a layman or a material dumbed down for laymen.

Literally nobody in the industry uses it that way.
 

Online RoGeorgeTopic starter

  • Super Contributor
  • ***
  • Posts: 6791
  • Country: ro
Re: Hrrmmm. Learn to code a linux driver you must. It's easy. Hmm.
« Reply #3 on: September 17, 2023, 09:22:09 am »
A software jedi master Yoda is not.  Yrsssss!  >:(



Try to write a driver e.g. for a new block device or some USB device, then the "It's easy" would have more relevance  ;)

Master Yoda said  "No, try not.  Do, or do not."  :)


Starting a drivers-101 with a block device might be a block.  Even the pros want them gone, like in FreeBSD:
Quote
9.4. Block Devices (Are Gone)

Other UNIX® systems may support a second type of disk device known as block devices. Block devices are disk devices for which the kernel provides caching. This caching makes block-devices almost unusable, or at least dangerously unreliable. The caching will reorder the sequence of write operations, depriving the application of the ability to know the exact disk contents at any one instant in time.

This makes predictable and reliable crash recovery of on-disk data structures (filesystems, databases, etc.) impossible. Since writes may be delayed, there is no way the kernel can report to the application which particular write operation encountered a write error, this further compounds the consistency problem.

For this reason, no serious applications rely on block devices, and in fact, almost all applications which access disks directly take great pains to specify that character (or "raw") devices should always be used. As the implementation of the aliasing of each disk (partition) to two devices with different semantics significantly complicated the relevant kernel code, FreeBSD dropped support for cached disk devices as part of the modernization of the disk I/O infrastructure.
Source:  https://docs.freebsd.org/en/books/arch-handbook/driverbasics/#driverbasics-block

Then, the USB is as its name tells:  universal, with so many possibilities it will confuse anyone at some point.
« Last Edit: September 17, 2023, 09:47:35 am by RoGeorge »
 

Offline DiTBho

  • Super Contributor
  • ***
  • Posts: 4247
  • Country: gb
Re: Hrrmmm. Learn to code a linux driver you must. It's easy. Hmm.
« Reply #4 on: September 17, 2023, 02:45:20 pm »
Most drivers are modules these days but not every module is a driver and not every driver is/can be a module.

I still have a serious problem with the kernel module of a fiber optic card. After thousands of hours of debugging I still haven't understood why if compiled statically (kernel built-in) the probe succeeds, while if compiled as a module it fails randomly.

It cannot be compiled as kernel module due to severe restrictions in the final embedded diskless environment, so it's ok as kernel built-in, but ... what the bloody hello is wrong with the Probe? It's just out of curiosity and I don't have time to investigate further as you have a layer of things to look at, starting with PCI, and then going up to all the layers above.

The next person who tells me "uh, oh, it's simple", I swear I'll throw the card at their head!
And it doesn't weigh little, it's 450g, coiunting a massive copper heatsink and thick connectors!
« Last Edit: September 17, 2023, 02:49:06 pm by DiTBho »
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 15423
  • Country: fr
Re: Hrrmmm. Learn to code a linux driver you must. It's easy. Hmm.
« Reply #5 on: September 17, 2023, 09:02:51 pm »
Most drivers are modules these days but not every module is a driver and not every driver is/can be a module.

I still have a serious problem with the kernel module of a fiber optic card. After thousands of hours of debugging I still haven't understood why if compiled statically (kernel built-in) the probe succeeds, while if compiled as a module it fails randomly.

While it's impossible to "debug" this particular issue from a distance and without any details, one general point that makes a difference between built-in kernel modules and loadable kernel modules is memory allocation, so that's what I would look at specifically first if I were to debug this.

There's a short introduction there: https://tldp.org/HOWTO/html_single/Module-HOWTO/#MEMALLOC
 
The following users thanked this post: DiTBho

Offline janoc

  • Super Contributor
  • ***
  • Posts: 3885
  • Country: de
Re: Hrrmmm. Learn to code a linux driver you must. It's easy. Hmm.
« Reply #6 on: September 18, 2023, 02:20:06 pm »
Starting a drivers-101 with a block device might be a block.  Even the pros want them gone, like in FreeBSD:

I wonder what relevance have FreeBSD drivers/manuals for writing Linux drivers?

This is way more relevant:
https://linux-kernel-labs.github.io/refs/heads/master/labs/block_device_drivers.html

Block device is something like a disk drive, RAID or e.g. USB mass storage and they certainly aren't going anywhere.

Then, the USB is as its name tells:  universal, with so many possibilities it will confuse anyone at some point.

I wonder whether you are a victim of a crappy clueless course or just trolling ...  :palm:
« Last Edit: September 18, 2023, 02:23:03 pm by janoc »
 

Online RoGeorgeTopic starter

  • Super Contributor
  • ***
  • Posts: 6791
  • Country: ro
Re: Hrrmmm. Learn to code a linux driver you must. It's easy. Hmm.
« Reply #7 on: September 18, 2023, 02:57:34 pm »
Most drivers are modules these days but not every module is a driver and not every driver is/can be a module.

I still have a serious problem with the kernel module of a fiber optic card. After thousands of hours of debugging I still haven't understood why if compiled statically (kernel built-in) the probe succeeds, while if compiled as a module it fails randomly.

It cannot be compiled as kernel module due to severe restrictions in the final embedded diskless environment, so it's ok as kernel built-in, but ... what the bloody hello is wrong with the Probe? It's just out of curiosity and I don't have time to investigate further as you have a layer of things to look at, starting with PCI, and then going up to all the layers above.

The next person who tells me "uh, oh, it's simple", I swear I'll throw the card at their head!
And it doesn't weigh little, it's 450g, coiunting a massive copper heatsink and thick connectors!

Keep in mind that what you just did, posting physical assault threats, is not something to joke about.

Nobody said "simple", title says "easy".  And it says that about writing a hello-world driver, doesn't say that about existing drivers, or about your FO card.  Please open a new topic if you need help with your card drivers, don't hijack this one.



The plan was to build both the hardware and the drivers for them, step by step.

The hardware was to come later, first example with an I2C device (for an analog multiplier, well, not exactly an analog multiplier but close, based on this idea:  https://hackaday.io/project/7542-rogeorge-cell).  The second hardware example was to be a PCIe JTAG with SN74BCT8245.

In the opening post there is no hardware, only the very first steps, setting the tools, compile an empty module, and load/unload it as a sanity check.  It was so in order to keep it short, and to test if there is any interest with the subject.

This topic was meant to be a joyful 101 journey on the land of PCIe bus and the Linux kernel.  It was meant for the absolute beginners, like me.

Well, I guess fouling around with a "Yoda speaking" title (without stating the goals) was a bad idea, or at least confusing, so just to make it clear, I am not Yoda.  ;D



To recap, from my side it looked like this:
- Hey, let's learn to write a Linux driver, look how easy could be.
- No, some are hard.  (OK, for sure some are, but learning has to start with something easy)
- I have the proof op is layman and shows dumbed down material.  (good observation, otherwise "literally nobody" might have missed that clue, and might have took Yoda phrasing as an academic paper)
- I am unable to compile and don't understand why, won't open my topic and will just vent here, and will break the head of whoever begs to differ my opinion!  (you OK now?)
- feeding the offtopic


What am I missing here?  Why trying to curb down the enthusiasm of others?
Did the planets just misaligned yesterday, or did I do something wrong?  :-//

Online IanB

  • Super Contributor
  • ***
  • Posts: 12401
  • Country: us
Re: Hrrmmm. Learn to code a linux driver you must. It's easy. Hmm.
« Reply #8 on: September 18, 2023, 06:09:47 pm »
Then, the USB is as its name tells:  universal, with so many possibilities it will confuse anyone at some point.

I wonder whether you are a victim of a crappy clueless course or just trolling ...  :palm:

The point to realize is that "USB" is not a device, it is a device bus (device interface) that can service many kinds of devices and device classes that might sit on the bus. So you have to write a driver for the device/USB combination, which will depend heavily on the kind of device. So it is, indeed, complicated.
 

Offline DiTBho

  • Super Contributor
  • ***
  • Posts: 4247
  • Country: gb
Re: Hrrmmm. Learn to code a linux driver you must. It's easy. Hmm.
« Reply #9 on: September 18, 2023, 06:46:57 pm »
posting physical assault threats

don't hijack this one.

physical assault?
hijack?

I did nothing but point out what has already been written to you by others: that is, that your topic title is all wrong, as well as your fanatical and ignorant attitude.

Sure, I did it in a jocking way

Quote from: DiTBho
The next person who tells me "uh, oh, it's simple", I swear I'll throw the card at their head!
And it doesn't weigh little, it's 450g, coiunting a massive copper heatsink and thick connectors!

no one threatens to physically hit anyone, it's just a jocking way to remind the reader of reality, that anything is neither "simple" nor "easy", and I think you have deliberately distorted the tone, in order to throw more mud.

I happen to develop/debug kernel modules for VxWorks, sometimes I have to "port" them to Linux. Sometimes I have to "debug" and "fix" other people' kernel modules, I know how frustrating it is, thus the reason for the jocking tone instead of throwing the same concept in your face with much more cynical ways and words: because dude, "code", "easy", "simple" only denote that you don't have no @#'£!$% idea what you're talking about, you just talk nonsense, as usual.

Seriously, enjoy my ignore list.
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 15423
  • Country: fr
Re: Hrrmmm. Learn to code a linux driver you must. It's easy. Hmm.
« Reply #10 on: September 18, 2023, 08:46:53 pm »
As a general thought, writing drivers for a micro-kernel tends to be much easier and less error-prone than for a monolithic kernel. Not that it helps if you have to deal with a Linux-based system.
 
The following users thanked this post: DiTBho

Online RoGeorgeTopic starter

  • Super Contributor
  • ***
  • Posts: 6791
  • Country: ro
Re: Hrrmmm. Learn to code a linux driver you must. It's easy. Hmm.
« Reply #11 on: September 18, 2023, 10:35:45 pm »
Starting a drivers-101 with a block device might be a block.  Even the pros want them gone, like in FreeBSD:

I wonder what relevance have FreeBSD drivers/manuals for writing Linux drivers?

Your post was pointing that drivers are not easy, and you were giving the examples of a block device and/or a USB driver as not easy, or at least that's what I understood.  True that, some drivers are not easy, but we don't want to discourage by starting with the most complicated.

Indeed, some drivers are so nasty that even the professional developers would want them gone, as for example in FreeBSD.  FreeBSD is not GNU/Linux, but I guess the difficulties for a block device driver are the same no matter the OS.  That's why bringing the FreeBSD.

Though, I never wrote such a driver for any modern OS, so I might be wrong with that guess.  The closest I've wrote was a driver for a floppy disk for CP/M, a very different OS and from long ago.  Not much would still apply today.



About the USB, it stands for Universal Serial Bus, and it is indeed "universal" if we think at the plethora of hardware that can make use of the USB.  No trolling, only a different viewpoint.  I'm an electronist, when I say USB I picture the hardware first.  Usually, by serial communication the default I picture is the UART.

Compared to the humble UART, USB has a very complicated behavior.  USB has many working modes, speed negotiation, it is plug and play, hot swapable, power/voltage negotiation, device enumeration, hubs, additional regulations for VID/PID allocation, and who knows what else.



So yes, you are correct, some drivers are far from easy, such as the two examples you gave.
Only argued against those examples in order to keep the learning easy, no trolling intended.

Offline Nominal Animal

  • Super Contributor
  • ***
  • Posts: 6953
  • Country: fi
    • My home page and email address
Re: Hrrmmm. Learn to code a linux driver you must. It's easy. Hmm.
« Reply #12 on: September 18, 2023, 11:01:58 pm »
Is anything worthwhile easy?  Among things that do not already exist, and haven't been reinvented time and time again?

I prefer to use 'straightforward', because when you know how the driver needs to operate, writing the code itself using the existing kernel guidelines is laborious but not difficult: it is a lot of work, but all the needed information and tools are available online for free.  It's like digging a ditch: the first thing to do is to ensure it is dug where it performs the desired purpose, and does not accidentally move a nearby lake a couple of miles in the wrong direction.

The difficult part about drivers is to find out exactly what the driver has to do to be useful, and what it needs to do to perform the desired task or tasks.  Stuff like locking, memory accounting, workers and workqueues, and so on.  This is both difficult (because of its complexity), taking a long time, but also requires experience, or you'll get bogged down in all the myriad traps for new players.  The design part is the hard part, not the coding part.

In DiTBho's case, probing order and hardware details, and having to maintain/backport/update/upgrade a driver someone else designed, I bet is a major source of pain.  Not Linux per se, unless you count in the "why doesn't this already exist in this form for this bloody arch?" sense.

As SiliconWizard mentioned, microkernel drivers tend to be easier to design because the privilege separation also forces one to use simpler interfaces between drivers and subsystems, so the design work is more structured.  In monolithic kernels, existing interfaces can have all sorts of inefficiencies and idiosyncracies.  In the case of the Linux kernel, those interfaces are constantly evolving; no stable kernel-internal interfaces exist at all.  The fewer subsystems a Linux driver interacts with, the easier it is to write; and vice versa.  PCI/PCIe + bus management + locking + memory can get quite hairy to properly design, and if you are "forced" to continue someone elses design you aren't even sure is sane, would give me the heebie-jeebies.  Add to more than one concurrent userspace user for that driver, and I start getting hives: designing something robust with that kind of complexity takes a lot of effort.

(I've long since learned to treat code rewrites as design-wide refactoring, where you use the old stuff to see what works, make that central and stable, and try to make it possible to try something better for the stuff the old stuff didn't do right.  Then again, even with a high output rate, that is not "a commercially viable use of development resources", because users are nowadays used (pun intended) to less than reliable tools; nobody is willing to pay for such work to be done.)

For USB devices, the usbfs /dev/bus/usb/jjj/kkk device interface is rather nice for userspace drivers.  It is no longer a separate filesystem in current kernels, and is included in the USB core, so its name is misleading; but it does support even async bulk and isochronous transfers and so on.

For anyone wishing/having to/considering doing Linux driver development, I do warmly recommend looking through the Linux Kernel Driver Implementer's API Guide, it being the documentation kernel developers themselves try to keep up to date.  Just getting an intuitive picture of how different drivers and hardware architectures work in Linux, will help with the difficult and hard driver design work.
 
The following users thanked this post: janoc, DiTBho


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf