OSDev.org

The Place to Start for Operating System Developers
It is currently Fri Mar 29, 2024 5:58 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 16 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Safer/better equivalent to ioctl?
PostPosted: Fri Mar 19, 2021 8:25 pm 
Offline
Member
Member

Joined: Sun Jun 23, 2019 5:36 pm
Posts: 618
Location: North Dakota, United States
So, I know that Linux (or Unix in general) has the ioctl(2) system call for generic device driver communication to avoid implementing millions of system calls for every kind of device driver in existence. I've never been a fan of ioctl myself; I feel like there should be a better way of approaching this. My idea might be to have an ahcictl, nvmectl, etc., for each kind of disk interface; ethernetctl/ethctl, wifictl for networking; and so on, and then maybe provide a C++ interface that uses function overloading to call the underlying interfaces. But I'm not really sure, so thought I might see what you guys think about just a generally better design other than ioctl().


Top
 Profile  
 
 Post subject: Re: Safer/better equivalent to ioctl?
PostPosted: Sat Mar 20, 2021 12:48 am 
Offline
Member
Member

Joined: Wed Aug 30, 2017 8:24 am
Posts: 1593
Alternatively, pseudo file systems. ioctl()s are about sending data to the kernel or retrieving data from the kernel. Both of these can be done with a pseudo-file. That gets around the issue of allocating tons of system call numbers for tons of niche interfaces. It also gets around some ridiculous ioctl()s, like the ones for setting IP addresses. You allocate some socket and use ioctl() on it. But there is never a need for any socket, you just need it as basis for the ioctl(). So maybe "echo 192.168.0.1/24>/net/if/eth0/ipv4/addr" is simpler than using that weirdness, or using "netlink", which Linux came up with. Don't get me wrong, netlink is great at giving you info you could not get otherwise, but for ad-hoc initialization like above IP address setting it is a bit overkill.

_________________
Carpe diem!


Top
 Profile  
 
 Post subject: Re: Safer/better equivalent to ioctl?
PostPosted: Sat Mar 20, 2021 7:44 am 
Offline
Member
Member

Joined: Sun Jun 23, 2019 5:36 pm
Posts: 618
Location: North Dakota, United States
That's... Actually a really good idea. So for NVMe controllers for example (following the FHS, you might have something like: /dev/nvme/nvme0/regs/cap/cmbs, which would access the CMBS bit of the CAP register. (Yeah, I know, devfs isn't commonly used like that -- that's more for /sys -- but it would make sense because /dev is for devices and device information.) Or, for the RTL 8139 you might have /dev/net/rtl0/mac for the MAC address.


Top
 Profile  
 
 Post subject: Re: Safer/better equivalent to ioctl?
PostPosted: Sat Mar 20, 2021 8:15 am 
Offline
Member
Member

Joined: Thu May 17, 2007 1:27 pm
Posts: 999
I am not sure if pseudo file systems really solve all use cases for ioctls. Pseudo FSes are great for non-performance critical stuff, but ioctls are also used for stuff like zero-copy I/O, and multiplexing that over write() is probably not a good idea. In particular, interpreting part of the written message as a pointer and dereferencing that in the kernel is probably a very bad idea, both for security reasons (e.g., you could trick a program to write to such a file to inject shellcode or extract data) and also because it restricts the implementation (e.g., it will break when used through a pipe to a different program).

You could always replace ioctls by native syscalls but then you need an efficient mechanism to dispatch these calls (and a simple lookup table won't work anymore). You could take an approach inspired by object-oriented programming. For example, you could group ioctls into "interfaces", have a syscall to request an interface handle for a pair of (fd, interface name), and then dispatch the ioctls as "syscalls" through the interface handle (i.e., on the kernel side, each interface would have its own syscall table).

_________________
managarm: Microkernel-based OS capable of running a Wayland desktop (Discord: https://discord.gg/7WB6Ur3). My OS-dev projects: [mlibc: Portable C library for managarm, qword, Linux, Sigma, ...] [LAI: AML interpreter] [xbstrap: Build system for OS distributions].


Top
 Profile  
 
 Post subject: Re: Safer/better equivalent to ioctl?
PostPosted: Sat Mar 20, 2021 11:34 am 
Offline
Member
Member

Joined: Sun Jun 23, 2019 5:36 pm
Posts: 618
Location: North Dakota, United States
Korona wrote:
I am not sure if pseudo file systems really solve all use cases for ioctls. Pseudo FSes are great for non-performance critical stuff, but ioctls are also used for stuff like zero-copy I/O, and multiplexing that over write() is probably not a good idea. In particular, interpreting part of the written message as a pointer and dereferencing that in the kernel is probably a very bad idea, both for security reasons (e.g., you could trick a program to write to such a file to inject shellcode or extract data) and also because it restricts the implementation (e.g., it will break when used through a pipe to a different program).

You could always replace ioctls by native syscalls but then you need an efficient mechanism to dispatch these calls (and a simple lookup table won't work anymore). You could take an approach inspired by object-oriented programming. For example, you could group ioctls into "interfaces", have a syscall to request an interface handle for a pair of (fd, interface name), and then dispatch the ioctls as "syscalls" through the interface handle (i.e., on the kernel side, each interface would have its own syscall table).

I'm confused. Are you saying that the syscall handler for instance would require something like an interface ID and then the syscall number, followed by arguments? Something like what UEFI does with its protocol handles?


Top
 Profile  
 
 Post subject: Re: Safer/better equivalent to ioctl?
PostPosted: Sat Mar 20, 2021 1:01 pm 
Offline
Member
Member

Joined: Thu May 17, 2007 1:27 pm
Posts: 999
Yes (that would be one possibility).

_________________
managarm: Microkernel-based OS capable of running a Wayland desktop (Discord: https://discord.gg/7WB6Ur3). My OS-dev projects: [mlibc: Portable C library for managarm, qword, Linux, Sigma, ...] [LAI: AML interpreter] [xbstrap: Build system for OS distributions].


Top
 Profile  
 
 Post subject: Re: Safer/better equivalent to ioctl?
PostPosted: Sat Mar 20, 2021 11:13 pm 
Offline
Member
Member

Joined: Wed Aug 30, 2017 8:24 am
Posts: 1593
Korona wrote:
You could always replace ioctls by native syscalls but then you need an efficient mechanism to dispatch these calls (and a simple lookup table won't work anymore). You could take an approach inspired by object-oriented programming. For example, you could group ioctls into "interfaces", have a syscall to request an interface handle for a pair of (fd, interface name), and then dispatch the ioctls as "syscalls" through the interface handle (i.e., on the kernel side, each interface would have its own syscall table).
You know, I hadn't though of that. That sounds like a good idea as well, particularly for those ioctl()s that actually do use the FD, e.g. TCSETATTR. I've been searching for some way to make terminal attributes into a pseudo-file that applications can still find reliably. The problem is that in general, finding the file name for a file descriptor can be pretty hard. Even if you have /proc/self/fd in your OS, readlink() is a messy interface. The code I came up with to read an arbitrary link requires malloc() in a loop. And the kernel definitely knows the terminal attached to the file descriptor directly. So this all seemed a bit pointless. Also, suddenly your applications all need to know about the different types of terminal device in your OS. And you have more dependencies on the VFS being configured in a particular way.

So having these interfaces and request them directly on the FD seems like a good idea for those types of ioctl()s. Also sound data. The old OSS would work by letting you open /dev/dsp and writing your sound samples to the device. Problem 1: What if you have multiple sound cards? OK, make /dev/dsp0, /dev/dsp1, ... and /dev/dsp is a symlink to your default device. Problem 2: How to configure the card? ioctl(). *sigh*. And then ALSA came along and said "ioctl() makes you sigh? Well, here's loads more of them!" And now there are ioctl()s for everything. You don't even write your samples to the device, you transfer them by ioctl(). So that seems like a thing I could quarantine away with those interfaces.

_________________
Carpe diem!


Top
 Profile  
 
 Post subject: Re: Safer/better equivalent to ioctl?
PostPosted: Sun Mar 21, 2021 6:27 am 
Offline
Member
Member

Joined: Sun Jun 23, 2019 5:36 pm
Posts: 618
Location: North Dakota, United States
For sound especially, I was thinking of something like /dev/dspx/samples, which you'd write to. Every time you did the driver would update any metadata it needs to pass to the sound controller about the samples being processed -- things like position at any rate. Then you'd have somethign like /dev/dspx/sampleinfo, which would include general info about the samples being written, e.g.: sample rate, number of channels, interleaving status and such. Then you'd have /dev/dspx/cmd, which would allow you to tell the driver when to actually begin processing the samples. That would make it easier to write streams in bulk.


Top
 Profile  
 
 Post subject: Re: Safer/better equivalent to ioctl?
PostPosted: Sun Mar 21, 2021 9:31 am 
Offline
Member
Member
User avatar

Joined: Mon Jun 05, 2006 11:00 pm
Posts: 2293
Location: USA (and Australia)
Do you want to keep the Unix philosophy of making everything a file?

_________________
My OS is Perception.


Top
 Profile  
 
 Post subject: Re: Safer/better equivalent to ioctl?
PostPosted: Sun Mar 21, 2021 8:13 pm 
Offline
Member
Member

Joined: Sun Jun 23, 2019 5:36 pm
Posts: 618
Location: North Dakota, United States
Not really. I think that descriptors for disks, files, etc., should be separate and there shouldn't be a universal "handle" for everything (that makes type checking kinda difficult). I also feel like devices/sockets/etc. shouldn't be treated as a part of the file system because they really, really are independent entities with pretty much nothing in common with each other other than being able to read from and write to them.


Top
 Profile  
 
 Post subject: Re: Safer/better equivalent to ioctl?
PostPosted: Sun Mar 21, 2021 8:52 pm 
Offline
Member
Member
User avatar

Joined: Mon Jun 05, 2006 11:00 pm
Posts: 2293
Location: USA (and Australia)
I went a different route in my OS and made a system where programs could implement and discover named services. The names are fully qualified, e.g. "perception.devices.StorageDevice".

Anyone who wants to build a storage device driver can implement and register the StorageDevice interface, and my VFS will be monitoring for when a new StorageDevice service is registered.

My graphics driver implements "perception.devices.GraphicsDevice", my window manager implements "perception.WindowManager", etc.

I came up with my own interface descriptor language, that lists methods and the request/response types, and it generates a C++ stub for calling and implementing the methods.

See: https://wiki.osdev.org/Remote_Procedure_Call
Inspiration: https://grpc.io/ https://thrift.apache.org/
What my IDL looks like: https://github.com/AndrewAPrice/Percept ... n/permebuf

_________________
My OS is Perception.


Top
 Profile  
 
 Post subject: Re: Safer/better equivalent to ioctl?
PostPosted: Sun Mar 21, 2021 10:07 pm 
Offline

Joined: Wed May 07, 2008 5:06 am
Posts: 19
Ethin wrote:
Not really. I think that descriptors for disks, files, etc., should be separate and there shouldn't be a universal "handle" for everything (that makes type checking kinda difficult). I also feel like devices/sockets/etc. shouldn't be treated as a part of the file system because they really, really are independent entities with pretty much nothing in common with each other other than being able to read from and write to them.


If you do that, you lose the device-independent I/O that is relatively common in Unix. For instance, it's very common to have programs that can do I/O to either a terminal or a disk file without having to be aware of any differences between the two, and if you make those completely separate, then every program has to be specifically aware of every possible device type, which I would say is a big step backwards. It also makes security a lot more complex if you have separate primitives for each device because each has to have its own separate security layer (which already makes security way more complicated than it needs to be on conventional Unices with their multiple non-file-based primitives), whereas in an OS with a purely file-oriented architecture you basically only have to have one relatively simple security layer for the entire system. In addition, file-oriented architecture with per-process namespaces makes containerization and multiple instances of system services a lot easier.

UX/RT, the OS I'm working on, will basically do the opposite of what you're proposing and take "everything is a file" as far as it can be taken (anonymous memory will be replaced with files in a tmpfs, process/thread creation will be done through procfs, and even most filesystem APIs themselves other than reads/writes will go through an RPC connection over a file descriptor). Any service that an OS implements can be built on top of receive/send or read/write primitives (in a typical microkernel OS everything actually is), so why overcomplicate things by having more primitives than you need? It's always possible to provide interface libraries on top of the file-based interfaces for services where it isn't convenient to use the file-based interface directly (UX/RT will do this for most of its APIs).

_________________
Developer of UX/RT, a QNX/Plan 9-like OS


Top
 Profile  
 
 Post subject: Re: Safer/better equivalent to ioctl?
PostPosted: Mon Mar 22, 2021 4:28 am 
Offline
Member
Member
User avatar

Joined: Mon Jun 05, 2006 11:00 pm
Posts: 2293
Location: USA (and Australia)
andrew_w wrote:
If you do that, you lose the device-independent I/O that is relatively common in Unix. For instance, it's very common to have programs that can do I/O to either a terminal or a disk file without having to be aware of any differences between the two, and if you make those completely separate, then every program has to be specifically aware of every possible device type, which I would say is a big step backwards. It also makes security a lot more complex if you have separate primitives for each device because each has to have its own separate security layer (which already makes security way more complicated than it needs to be on conventional Unices with their multiple non-file-based primitives), whereas in an OS with a purely file-oriented architecture you basically only have to have one relatively simple security layer for the entire system. In addition, file-oriented architecture with per-process namespaces makes containerization and multiple instances of system services a lot easier.


You get piping (piping one program's stdout to another's stdin or a file, which should be the job of the shell), but I can't really think of a concrete example where two totally different classes of devices would pipe ioctls with the other understanding it?

andrew_w wrote:
then every program has to be specifically aware of every possible device type


Does every program need to touch every device, other than your device manager that can scan and load drivers?

If you use an IDL to define an interface per device class, and you had a legitimate need to pretend your joystick is an Ethernet card, you can create a wrapper program that implements a virtual Ethernet card and transforms the command to joystick commands.

So as a concrete example, let's say you had a program that distorted your voice and you wanted to pipe your microphone to it, then pipe the outputs to your speaker, you could do:

Code:
voice_transformer < /device/microphone > /devices/speaker


Whereas, I'm proposing it's not too much of an ask to build a util file called "print_microphone" and "play_stdin", put it on the package manager/app store, and now you can do:
Code:
print_microphone --depth=24 --rate=96 | voice_transformer | play_stdin --depth=24 --rate=96


I'm not proposing it's better than "everything is a file", but the fun thing about OS Dev is if you're not interested in making a Unix clone you're free to explore whatever system you'd like.

_________________
My OS is Perception.


Last edited by AndrewAPrice on Mon Mar 22, 2021 10:56 am, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: Safer/better equivalent to ioctl?
PostPosted: Mon Mar 22, 2021 8:16 am 
Offline
Member
Member

Joined: Tue Feb 18, 2020 3:29 pm
Posts: 1071
In my OS, I am going to make an object manager. Drivers will get registered in the object manager. They can register functions for different tasks. For example, a driver would be registered. It would then make I/O control handlers in the object dispatch table. An app would grab the table, read the message numbers that correspond to a specific control (as my OS will be microkernel based) and then send a message with the proper parameters. I don't plan on making a strict Unix clone, rather something kind of Unix like.

_________________
"How did you do this?"
"It's very simple — you read the protocol and write the code." - Bill Joy
Projects: NexNix | libnex | nnpkg


Top
 Profile  
 
 Post subject: Re: Safer/better equivalent to ioctl?
PostPosted: Tue Mar 23, 2021 8:33 am 
Offline
Member
Member

Joined: Wed Oct 01, 2008 1:55 pm
Posts: 3192
My view is that ioctl is a completely useless interface, and by not implementing it you can stop device driver manufacturers and kernel gurus from modifying their devices or the kernel with undocumented APIs. If a function is important to support, you provide API functions for it, and if it simply is something fancy a hw manufacturer wants to push, then they can either configure it with environmental variables or do some automatic configuration. Of course, unless the OS team thinks it is something useful that more than one device supports, and then provide a new API for it.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 16 posts ]  Go to page 1, 2  Next

All times are UTC - 6 hours


Who is online

Users browsing this forum: Google [Bot], Majestic-12 [Bot] and 189 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group