Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 6 Apr 2024 14:39:26 -0600
From:      Warner Losh <imp@bsdimp.com>
To:        Rocky Hotas <rockyhotas@tilde.team>
Cc:        FreeBSD Hackers <freebsd-hackers@freebsd.org>
Subject:   Re: Kernel module: return a number from a device
Message-ID:  <CANCZdfqAUWqp_s8ULhi9A97jrMCxA1CAXJKmUJ307=PSpekKug@mail.gmail.com>
In-Reply-To: <oghsl7sgcl6p6ym3wwa3w56hn52cdophcr4jxau4ronxevy4ar@ux223whjcthj>
References:  <oghsl7sgcl6p6ym3wwa3w56hn52cdophcr4jxau4ronxevy4ar@ux223whjcthj>

next in thread | previous in thread | raw e-mail | index | archive | help

[-- Attachment #1 --]
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);
>
>

[-- Attachment #2 --]
<div dir="auto">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).<div dir="auto"><br></div><div dir="auto">Warner </div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sat, Apr 6, 2024, 2:27 PM Rocky Hotas &lt;rockyhotas@tilde.team&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hello!<br>
I&#39;m trying to write a simple kernel module, using as a model the example<br>
in<br>
<br>
 &lt;<a href="https://docs.freebsd.org/en/books/arch-handbook/driverbasics/" rel="noreferrer noreferrer" target="_blank">https://docs.freebsd.org/en/books/arch-handbook/driverbasics/</a>&gt;<br>;
<br>
I am a newbie. My module should be simpler than the one in the link: it<br>
should just create a read-only /dev/rolld file; each time it is read<br>
by the user (for example through `cat&#39;), the file should provide a<br>
random number mod d_size. So, the &quot;output&quot; should always be 1 character.<br>
<br>
I modified the echo kernel module presented in the link. My module<br>
can successfully be loaded into the kernel and the device is created,<br>
but if I run as a user `cat /dev/rolld&#39;:<br>
<br>
$ cat /dev/rolld <br>
Opened device &quot;rolld&quot; successfully.<br>
<br>
and it hangs, giving no more output and without generating an error.<br>
<br>
May be this due to the fact that uiomove receives a pointer &amp;random_out,<br>
which is a pointer to a uint32_t instead of for example a char? (And if<br>
this is the issue, how to convert a uint32_t to char inside the kernel?)<br>
<br>
Or is there some other error that I made?<br>
<br>
I paste my code below.<br>
<br>
Bye!<br>
<br>
Rocky<br>
<br>
<br>
<br>
#include &lt;sys/types.h&gt;<br>
#include &lt;sys/systm.h&gt;<br>
#include &lt;sys/param.h&gt;<br>
#include &lt;sys/module.h&gt;<br>
#include &lt;sys/kernel.h&gt;<br>
#include &lt;sys/conf.h&gt;<br>
#include &lt;sys/uio.h&gt;<br>
#include &lt;sys/malloc.h&gt;<br>
#include &lt;sys/libkern.h&gt;<br>
<br>
static d_open_t      rolld_open;<br>
static d_close_t     rolld_close;<br>
static d_read_t      rolld_read;<br>
<br>
static struct cdevsw rolld_cdevsw = {<br>
        .d_version = D_VERSION,<br>
        .d_open = rolld_open,<br>
        .d_close = rolld_close,<br>
        .d_read = rolld_read,<br>
        .d_name = &quot;rolld&quot;,<br>
};<br>
<br>
/* vars */<br>
static struct cdev *rolld_dev;<br>
static uint32_t d_size = 6;<br>
<br>
static int<br>
rolld_loader(struct module *m __unused, int what, void *arg __unused)<br>
{<br>
        int error = 0;<br>
<br>
        switch (what) {<br>
        case MOD_LOAD:                /* kldload */<br>
                error = make_dev_p(MAKEDEV_CHECKNAME | MAKEDEV_WAITOK,<br>
                    &amp;rolld_dev,<br>
                    &amp;rolld_cdevsw,<br>
                    0,<br>
                    UID_ROOT,<br>
                    GID_WHEEL,<br>
                    0444,<br>
                    &quot;rolld&quot;);<br>
                if (error != 0)<br>
                        break;<br>
<br>
                printf(&quot;Roll device loaded.\n&quot;);<br>
                break;<br>
        case MOD_UNLOAD:<br>
                destroy_dev(rolld_dev);<br>
                printf(&quot;Roll device unloaded.\n&quot;);<br>
                break;<br>
        default:<br>
                error = EOPNOTSUPP;<br>
                break;<br>
        }<br>
        return (error);<br>
}<br>
<br>
static int<br>
rolld_open(struct cdev *dev __unused, int oflags __unused, int devtype __unused,<br>
    struct thread *td __unused)<br>
{<br>
        int error = 0;<br>
<br>
        uprintf(&quot;Opened device \&quot;rolld\&quot; successfully.\n&quot;);<br>
        return (error);<br>
}<br>
<br>
static int<br>
rolld_close(struct cdev *dev __unused, int fflag __unused, int devtype __unused,<br>
    struct thread *td __unused)<br>
{<br>
        uprintf(&quot;Closing device \&quot;rolld\&quot;.\n&quot;);<br>
        return (0);<br>
}<br>
<br>
static int<br>
rolld_read(struct cdev *dev __unused, struct uio *uio, int ioflag __unused)<br>
{<br>
        uint32_t random_out;<br>
        uint32_t random_item;<br>
        int error;<br>
<br>
        random_item = arc4random();<br>
        random_out = random_item % d_size;<br>
<br>
        if ((error = uiomove(&amp;random_out, 1, uio)) != 0)<br>
                uprintf(&quot;uiomove failed!\n&quot;);<br>
<br>
        return (error);<br>
}<br>
<br>
DEV_MODULE(rolld, rolld_loader, NULL);<br>
<br>
</blockquote></div>

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CANCZdfqAUWqp_s8ULhi9A97jrMCxA1CAXJKmUJ307=PSpekKug>