Re: Kernel module: return a number from a device
- In reply to: Rocky Hotas : "Kernel module: return a number from a device"
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 06 Apr 2024 20:39:26 UTC
When this happens, hit ^t (control t). That will give a traceback of the
call stack which may help you track down where it is hanging (most likely
something is sleeping waiting for an event).
Warner
On Sat, Apr 6, 2024, 2:27 PM Rocky Hotas <rockyhotas@tilde.team> wrote:
> Hello!
> I'm trying to write a simple kernel module, using as a model the example
> in
>
> <https://docs.freebsd.org/en/books/arch-handbook/driverbasics/>
>
> I am a newbie. My module should be simpler than the one in the link: it
> should just create a read-only /dev/rolld file; each time it is read
> by the user (for example through `cat'), the file should provide a
> random number mod d_size. So, the "output" should always be 1 character.
>
> I modified the echo kernel module presented in the link. My module
> can successfully be loaded into the kernel and the device is created,
> but if I run as a user `cat /dev/rolld':
>
> $ cat /dev/rolld
> Opened device "rolld" successfully.
>
> and it hangs, giving no more output and without generating an error.
>
> May be this due to the fact that uiomove receives a pointer &random_out,
> which is a pointer to a uint32_t instead of for example a char? (And if
> this is the issue, how to convert a uint32_t to char inside the kernel?)
>
> Or is there some other error that I made?
>
> I paste my code below.
>
> Bye!
>
> Rocky
>
>
>
> #include <sys/types.h>
> #include <sys/systm.h>
> #include <sys/param.h>
> #include <sys/module.h>
> #include <sys/kernel.h>
> #include <sys/conf.h>
> #include <sys/uio.h>
> #include <sys/malloc.h>
> #include <sys/libkern.h>
>
> static d_open_t rolld_open;
> static d_close_t rolld_close;
> static d_read_t rolld_read;
>
> static struct cdevsw rolld_cdevsw = {
> .d_version = D_VERSION,
> .d_open = rolld_open,
> .d_close = rolld_close,
> .d_read = rolld_read,
> .d_name = "rolld",
> };
>
> /* vars */
> static struct cdev *rolld_dev;
> static uint32_t d_size = 6;
>
> static int
> rolld_loader(struct module *m __unused, int what, void *arg __unused)
> {
> int error = 0;
>
> switch (what) {
> case MOD_LOAD: /* kldload */
> error = make_dev_p(MAKEDEV_CHECKNAME | MAKEDEV_WAITOK,
> &rolld_dev,
> &rolld_cdevsw,
> 0,
> UID_ROOT,
> GID_WHEEL,
> 0444,
> "rolld");
> if (error != 0)
> break;
>
> printf("Roll device loaded.\n");
> break;
> case MOD_UNLOAD:
> destroy_dev(rolld_dev);
> printf("Roll device unloaded.\n");
> break;
> default:
> error = EOPNOTSUPP;
> break;
> }
> return (error);
> }
>
> static int
> rolld_open(struct cdev *dev __unused, int oflags __unused, int devtype
> __unused,
> struct thread *td __unused)
> {
> int error = 0;
>
> uprintf("Opened device \"rolld\" successfully.\n");
> return (error);
> }
>
> static int
> rolld_close(struct cdev *dev __unused, int fflag __unused, int devtype
> __unused,
> struct thread *td __unused)
> {
> uprintf("Closing device \"rolld\".\n");
> return (0);
> }
>
> static int
> rolld_read(struct cdev *dev __unused, struct uio *uio, int ioflag __unused)
> {
> uint32_t random_out;
> uint32_t random_item;
> int error;
>
> random_item = arc4random();
> random_out = random_item % d_size;
>
> if ((error = uiomove(&random_out, 1, uio)) != 0)
> uprintf("uiomove failed!\n");
>
> return (error);
> }
>
> DEV_MODULE(rolld, rolld_loader, NULL);
>
>