When working with sysfs GPIO on Linux, you are instructed to poll
for POLLPRI
and POLLERR
events.
This is quite easy:
poll = select.poll()
poll.register(filename, select.POLLPRI | select.POLLERR)
result = poll.poll(timeout=timeout)
However, I would like to write tests for this code, and simulation tests for the application relying on it. So, I need to be able to cause a POLLPRI
event.
I have tried using a Unix domain socket, but then I am unable to open the file for reading after the domain socket has connected (errno 6
, no such device). I also tried using a socket with SOCK_DGRAM
, but that either fails to find the file if not already created, or yields connection refused.
I want a way to open a regular file or create a file that can be opened like a regular file and be able to send it a stream of messages that are treated as "urgent data". ie MSG_OOB
.
What can I do?
It looks like you can achieve this by polling a sysctl exposed in procfs. If you look at the poll implementation in procfs for the sys
subdirectory, you'll see that any sysctl that implements notifications for poll will return a mask that includes POLLERR|POLLPRI
. So how do we figure out what sysctls implement this? We look for uses of proc_sys_poll_notify
!
One such place is in proc_do_uts_string
, which implements a number of sysctls under /proc/sys/kernel
. Most of these are read-only, but hostname
and domainname
can be written (see also their table entries).
Of course, this is going to require root privileges to be able to write to e.g. /proc/sys/kernel/hostname
.
This is probably the easiest way to do such a thing while staying within a synthetic filesystem implementation. Of course, the only real way to test your code is to poll(2)
one of your pins, press a button, and see if you get your rising / falling signal interrupts.
Note: sysfs also does this for edge nodes in the tree:
>>> import select
>>> f = open('/sys/bus/clockevents/devices/clockevent0/uevent', 'r')
>>> p = select.poll()
>>> p.register(f, select.POLLPRI | select.POLLERR)
>>> result = p.poll(10)
>>> result
[(3, 10)]
10
is of course POLLPRI (0x2) | POLLERR (0x8)
. I got the same results using /sys/power/state
as my input. Basically, if you poll any user-readable, non-directory file entry in sysfs, you'll get POLLPRI | POLLERR
back.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With