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
--00000000000036ce4a06157392a6
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

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=E2=80=AFPM Rocky Hotas <rockyhotas@tilde.team> wr=
ote:

> 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 =3D {
>         .d_version =3D D_VERSION,
>         .d_open =3D rolld_open,
>         .d_close =3D rolld_close,
>         .d_read =3D rolld_read,
>         .d_name =3D "rolld",
> };
>
> /* vars */
> static struct cdev *rolld_dev;
> static uint32_t d_size =3D 6;
>
> static int
> rolld_loader(struct module *m __unused, int what, void *arg __unused)
> {
>         int error =3D 0;
>
>         switch (what) {
>         case MOD_LOAD:                /* kldload */
>                 error =3D make_dev_p(MAKEDEV_CHECKNAME | MAKEDEV_WAITOK,
>                     &rolld_dev,
>                     &rolld_cdevsw,
>                     0,
>                     UID_ROOT,
>                     GID_WHEEL,
>                     0444,
>                     "rolld");
>                 if (error !=3D 0)
>                         break;
>
>                 printf("Roll device loaded.\n");
>                 break;
>         case MOD_UNLOAD:
>                 destroy_dev(rolld_dev);
>                 printf("Roll device unloaded.\n");
>                 break;
>         default:
>                 error =3D EOPNOTSUPP;
>                 break;
>         }
>         return (error);
> }
>
> static int
> rolld_open(struct cdev *dev __unused, int oflags __unused, int devtype
> __unused,
>     struct thread *td __unused)
> {
>         int error =3D 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 __unuse=
d)
> {
>         uint32_t random_out;
>         uint32_t random_item;
>         int error;
>
>         random_item =3D arc4random();
>         random_out =3D random_item % d_size;
>
>         if ((error =3D uiomove(&random_out, 1, uio)) !=3D 0)
>                 uprintf("uiomove failed!\n");
>
>         return (error);
> }
>
> DEV_MODULE(rolld, rolld_loader, NULL);
>
>

--00000000000036ce4a06157392a6
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"auto">When this happens, hit ^t (control t). That will give a t=
raceback of the call stack which may help you track down where it is hangin=
g (most likely something is sleeping waiting for an event).<div dir=3D"auto=
"><br></div><div dir=3D"auto">Warner=C2=A0</div></div><br><div class=3D"gma=
il_quote"><div dir=3D"ltr" class=3D"gmail_attr">On Sat, Apr 6, 2024, 2:27=
=E2=80=AFPM Rocky Hotas &lt;rockyhotas@tilde.team&gt; wrote:<br></div><bloc=
kquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #cc=
c solid;padding-left:1ex">Hello!<br>
I&#39;m trying to write a simple kernel module, using as a model the exampl=
e<br>
in<br>
<br>
=C2=A0&lt;<a href=3D"https://docs.freebsd.org/en/books/arch-handbook/driver=
basics/" rel=3D"noreferrer noreferrer" target=3D"_blank">https://docs.freeb=
sd.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 cha=
racter.<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=C2=A0 =C2=A0 =C2=A0 rolld_open;<br>
static d_close_t=C2=A0 =C2=A0 =C2=A0rolld_close;<br>
static d_read_t=C2=A0 =C2=A0 =C2=A0 rolld_read;<br>
<br>
static struct cdevsw rolld_cdevsw =3D {<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 .d_version =3D D_VERSION,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 .d_open =3D rolld_open,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 .d_close =3D rolld_close,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 .d_read =3D rolld_read,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 .d_name =3D &quot;rolld&quot;,<br>
};<br>
<br>
/* vars */<br>
static struct cdev *rolld_dev;<br>
static uint32_t d_size =3D 6;<br>
<br>
static int<br>
rolld_loader(struct module *m __unused, int what, void *arg __unused)<br>
{<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 int error =3D 0;<br>
<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 switch (what) {<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 case MOD_LOAD:=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 /* kldload */<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 error =3D make_dev_=
p(MAKEDEV_CHECKNAME | MAKEDEV_WAITOK,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &amp;=
rolld_dev,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &amp;=
rolld_cdevsw,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0,<br=
>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UID_R=
OOT,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 GID_W=
HEEL,<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0444,=
<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &quot=
;rolld&quot;);<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (error !=3D 0)<b=
r>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 break;<br>
<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 printf(&quot;Roll d=
evice loaded.\n&quot;);<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 break;<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 case MOD_UNLOAD:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 destroy_dev(rolld_d=
ev);<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 printf(&quot;Roll d=
evice unloaded.\n&quot;);<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 break;<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 default:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 error =3D EOPNOTSUP=
P;<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 break;<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 }<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 return (error);<br>
}<br>
<br>
static int<br>
rolld_open(struct cdev *dev __unused, int oflags __unused, int devtype __un=
used,<br>
=C2=A0 =C2=A0 struct thread *td __unused)<br>
{<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 int error =3D 0;<br>
<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 uprintf(&quot;Opened device \&quot;rolld\&quot;=
 successfully.\n&quot;);<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 return (error);<br>
}<br>
<br>
static int<br>
rolld_close(struct cdev *dev __unused, int fflag __unused, int devtype __un=
used,<br>
=C2=A0 =C2=A0 struct thread *td __unused)<br>
{<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 uprintf(&quot;Closing device \&quot;rolld\&quot=
;.\n&quot;);<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 return (0);<br>
}<br>
<br>
static int<br>
rolld_read(struct cdev *dev __unused, struct uio *uio, int ioflag __unused)=
<br>
{<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 uint32_t random_out;<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 uint32_t random_item;<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 int error;<br>
<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 random_item =3D arc4random();<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 random_out =3D random_item % d_size;<br>
<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 if ((error =3D uiomove(&amp;random_out, 1, uio)=
) !=3D 0)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 uprintf(&quot;uiomo=
ve failed!\n&quot;);<br>
<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 return (error);<br>
}<br>
<br>
DEV_MODULE(rolld, rolld_loader, NULL);<br>
<br>
</blockquote></div>

--00000000000036ce4a06157392a6--



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