Skip to contentSkip to conversation

CHAR DRIVERS: a simple device to give daemons a /sys-like interface

PATCH In review Bob Smith 5 participants 36 messages Aug 3, 2013 – Aug 13, 2013 1 message not in the archive

Subsystems (2)
lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): [email protected]

Bob Smith

author
#1 lore raw

PATCH 1/1 CHAR DRIVERS: a simple device to give daemons a /sys-like interface

This character device can give daemons an interface similar to
the kernel's /sys and /proc interfaces. It is a nice way to
give user space drivers real device nodes in /dev.

thanks
Bob Smith

From 7ee4391af95b828179cf5627f8b431c3301c5057 Mon Sep 17 00:00:00 2001
From: Bob Smith <[email protected]>
Date: Fri, 2 Aug 2013 16:44:48 -0700
Subject: [PATCH] PROXY, a driver that gives daemons a /sys like interface

---
 Documentation/proxy.txt |   36 ++++
 drivers/char/Kconfig    |    8 +
 drivers/char/Makefile   |    2 +-
 drivers/char/proxy.c    |  539 +++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 584 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/proxy.txt
 create mode 100644 drivers/char/proxy.c
Documentation/proxy.txt new file +36 -0
new file mode 100644
index 0000000..6b9206a
@@ -0,0 +1,36 @@
+Proxy Character Devices
+
+
+Proxy is a small character device that connects two user space
+processes.  It is intended to give user space daemons a /sys like
+interface for configuration and status.
+
+As an example consider a daemon that controls a stepper motor. The
+daemon would create and open one proxy device to read and write
+configuration (/dev/stepper/config) and another proxy device to
+accept a motor step count (/dev/stepper/count).
+Shell commands to illustrate this example:
+	$ stepper_daemon	# start the stepper control daemon
+	$ # Set config to full steps, clockwise and 400 step/sec
+	$ echo "full, cw, 400" > /dev/stepper/config
+	$ # Now tell the motor to step 4000 steps
+	$ echo 4000 > /dev/stepper/count
+	$ sleep 2
+	$ # How many steps remain?
+	$ cat /dev/stepper/count
+
+
+Proxy has some unique features that make ideal for providing a
+/sys like interface.  It has no internal buffering.  The means
+the daemon can not write until a client program is listening.
+Both named pipes and pseudo-ttys have internal buffers.
+
+Proxy will succeed on a write of zero bytes.  A zero byte write
+gives the client an EOF.  The daemon in the example above would
+use a zero byte write in the last command after it had written the
+number of steps remaining.  No other IPC mechanism can close one
+side of a device and leave the other side open.
+
+Proxy works well with select(), an important feature for daemons.
+In contrast, the FUSE filesystem has some issues with select() on
+the client side.
drivers/char/Kconfig +8 -0
index 1421997..d21ea1d 100644
@@ -566,6 +566,14 @@ config TELCLOCK
 	  /sys/devices/platform/telco_clock, with a number of files for
 	  controlling the behavior of this hardware.
 
+config PROXY
+	tristate "Proxy char device that gives daemons a /sys-like interface"
+	default n
+	help
+	  Proxy is a character device that minimally connects two user space
+	  processes.  It is intended to give user space daemons a /sys like
+	  interface for configuration and status.
+
 config DEVPORT
 	bool
 	depends on !M68K
drivers/char/Makefile +1 -1
index 7ff1d0d..7009038 100644
@@ -48,7 +48,7 @@ obj-$(CONFIG_PC8736x_GPIO)	+= pc8736x_gpio.o
 obj-$(CONFIG_NSC_GPIO)		+= nsc_gpio.o
 obj-$(CONFIG_GPIO_TB0219)	+= tb0219.o
 obj-$(CONFIG_TELCLOCK)		+= tlclk.o
-
+obj-$(CONFIG_PROXY)		+= proxy.o
 obj-$(CONFIG_MWAVE)		+= mwave/
 obj-$(CONFIG_AGP)		+= agp/
 obj-$(CONFIG_PCMCIA)		+= pcmcia/
drivers/char/proxy.c new file +539 -0

539 lines not on this page · raw message

Signature · 1 line
1.7.10.4
#2 lore raw
Quoted 3 lines · Bob Smith

This character device can give daemons an interface similar to
the kernel's /sys and /proc interfaces. It is a nice way to
give user space drivers real device nodes in /dev.

Trivial notes:

drivers/char/proxy.c

Quoted 1 line
drivers/char/proxy.c +0 -0

[]
+int proxy_init_module(void)

drivers/char/proxy.c line 144

Quoted 8 lines
drivers/char/proxy.c +8 -0
+{
+	int i, err;
+	px_devices = kmalloc(numberofdevs * sizeof(struct px), GFP_KERNEL);
+	if (px_devices == NULL) {
+		/* no memory available */
+		if (debuglevel >= 1)
+			pr_err("%s: init fails: no memory.\n",
+			       DEVNAME);

OOM messages aren't necessary.
dump_stack() is already done on OOM.

drivers/char/proxy.c line 147

Quoted 3 lines
drivers/char/proxy.c +3 -0
+		return 0;
+	}
+	memset(px_devices, 0, numberofdevs * sizeof(struct px));

kcalloc instead of kmalloc/memset

drivers/char/proxy.c line 157

Quoted 10 lines
drivers/char/proxy.c +10 -0
+
+	/* init devices in this block */
+	for (i = 0; i < numberofdevs; i++) {   /* for every minor device */
+		px_devices[i].minor = i;	  /* set minor number */
+		px_devices[i].ewbuf.buf = (char *) 0;
+		px_devices[i].webuf.buf = (char *) 0;
+		px_devices[i].ewbuf.widx = 0;
+		px_devices[i].webuf.widx = 0;
+		px_devices[i].ewbuf.ridx = 0;
+		px_devices[i].webuf.ridx = 0;

sets to zero after zeroed alloc are redundant.

drivers/char/proxy.c line 190

Quoted 7 lines
drivers/char/proxy.c +7 -0
+	err = cdev_add(&px_cdev, px_devicenumber, numberofdevs);
+	if (err < 0) {
+		if (debuglevel >= 1)
+			pr_err("%s: init fails. err=%d.\n",
+			       DEVNAME, err);
+		return err;
+	}

It's either an err or a debug message.
Don't hide actual errors under debugging levels.

I suggest you only use pr_debug and/or have a macro like

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#define proxy_dbg(level, fmt, ...) \

do {						\
	if (level >= debuglevel)		\
		pr_debug(fmt, ##__VA_ARGS__);	\
} while (0)

drivers/char/proxy.c line 194

Quoted 3 lines
drivers/char/proxy.c +3 -0
+	if (debuglevel >= 2)
+		pr_info("%s: Installed %d minor devices on major number %d.\n",
+		       DEVNAME, numberofdevs, px_major);

Then this (and the rest) becomes

		proxy_dbg(2, "Installed %d minor devices on major %d\n",
			  numberofdevs, px_major);

etc...

Quoted 9 lines
drivers/char/proxy.c +8 -0
+static int proxy_open(struct inode *inode, struct file *filp)
+{
 
+	if (!dev->ewbuf.buf) {			/* get east-to-west buffer */
+		dev->ewbuf.buf = kmalloc(buffersize, GFP_KERNEL);
+		if (!dev->ewbuf.buf) {
+			if (debuglevel >= 1)
+				pr_err("%s: No memory dev=%d.\n",
+				       DEVNAME, mnr);

drivers/char/proxy.c line 252

Quoted 10 lines
drivers/char/proxy.c +10 -0
+			up(&dev->sem);
+			return -ENOMEM;
+		}
+	}
+	if (!dev->webuf.buf) {			/* get west-to-east buffer */
+		dev->webuf.buf = kmalloc(buffersize, GFP_KERNEL);
+		if (!dev->webuf.buf) {
+			if (debuglevel >= 1)
+				pr_err("%s: No memory dev=%d.\n",
+				       DEVNAME, mnr);

no OOMs.

Quoted 5 lines
drivers/char/proxy.c +5 -0
+static int proxy_release(struct inode *inode, struct file *filp)
+{
+	struct px *dev = (struct px *) filp->private_data;
+
+	if (debuglevel >= 3)

drivers/char/proxy.c line 301

Quoted 10 lines
drivers/char/proxy.c +10 -0
+		pr_info("%s release. Minor#=%d.\n", DEVNAME,
+		       ((struct px *) filp->private_data)->minor);
+
+	if (down_interruptible(&dev->sem))	/* prevent races on close */
+		return -ERESTARTSYS;
+
+	dev->nopen = dev->nopen - 1;
+
+	if (dev->east == filp) {
+		dev->east = (struct file *) 0;	/* mark as not in use */

s/0/NULL; (no need to cast either)

drivers/char/proxy.c line 304

Quoted 3 lines
drivers/char/proxy.c +3 -0
+		dev->ewbuf.cidx = dev->ewbuf.widx; /* set close index */
+	} else if (dev->west == filp) {
+		dev->west = (struct file *) 0;	/* mark as not in use */

etc.

#3 lore raw
In reply to Bob Smith
Quoted 3 lines · Bob Smith

This character device can give daemons an interface similar to
the kernel's /sys and /proc interfaces. It is a nice way to
give user space drivers real device nodes in /dev.

Why not just use the cuse interface instead? How does this differ from that /dev node interaction?

And how does this have anything to do with /sys? I can't see any sysfs interaction in the code, or am I missing it?

thanks,

greg k-h

author
#4 lore raw

Greg
Thanks for your reply. I'll reply to your comments in reverse order.

Quoted 2 lines · Greg Kroah-Hartman

And how does this have anything to do with /sys? I can't see any sysfs interaction in the code, or am I missing it?

Yes, you are right. I'll change the subject and brief descriptions to something like:
"Proxy, a simple bidirectional character device that almost transparently proxies opens, reads, writes, and closes from one side of the device to the other side."

I'll take "/sys" from all descriptions of the device, but I might leave it in the Documentation/proxy.txt file since a major use case of proxy is to give user space drivers and daemons the same kind of interface the kernel enjoys with /sys and /proc. The similarity is very deliberate on my part for commands like
echo 1 > /proc/sys/net/ipv4/ip_forward # procfs
echo 75 > /dev/motors/left/speed # proxy dev

Quoted 2 lines · Greg Kroah-Hartman

Why not just use the cuse interface instead? How does this differ from that /dev node interaction?

I am a big fan of FUSE and CUSE but they do not support what I need. CUSE is OK if _ALL_ interaction is through its interface. What is lacking is an ability to open, say, a USB serial port and add its file descriptor to CUSE's FD_SET. This is a pretty deep problem since a CUSE takes away main() from the application developer. A CUSE application looks kind of like this:

	main(argc, argv)
	{
		(check and process command line)
		cuse_lowlevel_main(argc, argv, ...)
	}

Another difference is that no language bindings are needed. There is no equivalent of libfuse.so. Since proxy is just a character device and there are no language bindings, someone could, in the unlikely case it ever made sense, write a user space device driver in node.js.

thanks
Bob Smith

#5 lore raw
In reply to Bob Smith
Quoted 3 lines · Bob Smith

This character device can give daemons an interface similar to
the kernel's /sys and /proc interfaces. It is a nice way to
give user space drivers real device nodes in /dev.

Other comments about this patch:

Quoted 5 lines

From 7ee4391af95b828179cf5627f8b431c3301c5057 Mon Sep 17 00:00:00 2001
From: Bob Smith <[email protected]>
Date: Fri, 2 Aug 2013 16:44:48 -0700
Subject: [PATCH] PROXY, a driver that gives daemons a /sys like interface

No signed-off-by:, or body of text here that explains what this is and why it should be accepted.

Quoted 31 lines
---
 Documentation/proxy.txt |   36 ++++
 drivers/char/Kconfig    |    8 +
 drivers/char/Makefile   |    2 +-
 drivers/char/proxy.c    |  539 +++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 584 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/proxy.txt
 create mode 100644 drivers/char/proxy.c
Documentation/proxy.txt new file +16 -0
new file mode 100644
index 0000000..6b9206a
@@ -0,0 +1,36 @@
+Proxy Character Devices
+
+
+Proxy is a small character device that connects two user space
+processes.  It is intended to give user space daemons a /sys like
+interface for configuration and status.
+
+As an example consider a daemon that controls a stepper motor. The
+daemon would create and open one proxy device to read and write
+configuration (/dev/stepper/config) and another proxy device to
+accept a motor step count (/dev/stepper/count).
+Shell commands to illustrate this example:
+	$ stepper_daemon	# start the stepper control daemon
+	$ # Set config to full steps, clockwise and 400 step/sec
+	$ echo "full, cw, 400" > /dev/stepper/config
+	$ # Now tell the motor to step 4000 steps

Documentation/proxy.txt line 26

Quoted 10 lines
Documentation/proxy.txt new file +10 -0
+	$ echo 4000 > /dev/stepper/count
+	$ sleep 2
+	$ # How many steps remain?
+	$ cat /dev/stepper/count
+
+
+Proxy has some unique features that make ideal for providing a
+/sys like interface.  It has no internal buffering.  The means
+the daemon can not write until a client program is listening.
+Both named pipes and pseudo-ttys have internal buffers.

So what is wrong with internal buffers? Named pipes have been around for a long time, they should be able to be used much like this, right?

Documentation/proxy.txt line 32

Quoted 5 lines
Documentation/proxy.txt new file +5 -0
+Proxy will succeed on a write of zero bytes.  A zero byte write
+gives the client an EOF.  The daemon in the example above would
+use a zero byte write in the last command after it had written the
+number of steps remaining.  No other IPC mechanism can close one
+side of a device and leave the other side open.

No "direct" IPC, but you can always emulate this just fine with existing IPC mechanisms.

Documentation/proxy.txt line 36

Quoted 3 lines
Documentation/proxy.txt new file +3 -0
+Proxy works well with select(), an important feature for daemons.
+In contrast, the FUSE filesystem has some issues with select() on
+the client side.

What are those issues? Why not just fix them?

Adding a new IPC function to the kernel should not be burried down in drivers/char/. We have 10+ different IPC mechanisms already, some simple, some more complex. Are you _sure_ none of the existing ones will not work for you? Maybe a simple userspace library that wraps the existing mechanisms would be better (no kernel changes needed, portable to any kernel release, etc.)?

thanks,

greg k-h

author
#6 lore raw

Greg
I've added some white space and snipped some text to make
the questions more visible.

Quoted 2 lines · Greg Kroah-Hartman

No signed-off-by:, or body of text here that explains what this is and why it should be accepted.

D'oh! I'll fix this and add Joe's changes before resubmitting the patch.

BTW: Several people have said they don't understand how to use this device, so I'll give Documentation/proxy.txt a simple example program that illustrates the two most common uses cases.

Quoted 7 lines

Documentation/proxy.txt line 26

Quoted 4 lines
Documentation/proxy.txt new file +4 -0
+Proxy has some unique features that make ideal for providing a
+/sys like interface.  It has no internal buffering.  The means
+the daemon can not write until a client program is listening.
+Both named pipes and pseudo-ttys have internal buffers.

So what is wrong with internal buffers? Named pipes have been around for a long time, they should be able to be used much like this, right?

Buffers are great for streaming data but are unneeded for configuration and status information. Neither sysfs or procfs have internal buffers because they are not needed.
In a way the problem is not the buffer itself but that a write
into a named pipe, for example, will succeed even if there is no one at the other end to receive the data. I think you'd want an open and write on a device driver to fail if the driver is not there and ready for the request.

Quoted 6 lines
Quoted 4 lines
(quoted diff) +2 -0
+Proxy will succeed on a write of zero bytes.  A zero byte write
+gives the client an EOF.  (snip)

No other IPC mechanism can close one
+side of a device and leave the other side open.

No "direct" IPC, but you can always emulate this just fine with existing IPC mechanisms.

OK.

Quoted 4 lines

Documentation/proxy.txt line 36

Quoted 3 lines
Documentation/proxy.txt new file +3 -0
+Proxy works well with select(), an important feature for daemons.
+In contrast, the FUSE filesystem has some issues with select() on
+the client side.

What are those issues? Why not just fix them?

When I resubmit this patch, I'll remove all references to FUSE. There is nothing wrong with FUSE. It is just not the right tool for the this job. I shouldn't have build and load a full file system when all I want is a handful of device nodes.

Quoted 4 lines

Adding a new IPC function to the kernel should not be burried down in drivers/char/. We have 10+ different IPC mechanisms already, some simple, some more complex. Are you _sure_ none of the existing ones will not work for you?

I'm convinced this has the fewest lines of new code and the smallest impact on the rest of the system, but I could be wrong. The minimum feature set I want is to emulate for my user-space device driver what the kernel has for procfs and sysfs, That is,
echo 1 > /proc/sys/net/ipv4/ip_forward # procfs
echo 75 > /dev/motors/left/speed # proxy dev

Quoted 3 lines

Maybe a simple userspace library that wraps the
existing mechanisms would be better (no kernel changes needed, portable to any kernel release, etc.)?

Yes, this is the traditional model for approaching problems like the one I have. It would involve opening a unix socket, defining a protocol for that socket, and then writing several bindings for that protocol for different languages. Wow, that is a LOT of work.

Luckily for us the procfs and sysfs authors have given us a much
better model to use: ASCII characters terminated by a newline. My Raspberry Pi customers expect to control an LED with a command like
this: echo 1 > /sys/class/gpio/gpio25

So it is entirely reasonable on their part to want to control a stepper motor with a command like this:
echo 300 > /dev/robot/stepper0/count

Again, I hope you don't mind the text snip and extra white space.

thanks
Bob Smith

#7 lore raw
Quoted 10 lines · Bob Smith
Quoted 7 lines

Documentation/proxy.txt line 26

Quoted 4 lines
Documentation/proxy.txt new file +4 -0
+Proxy has some unique features that make ideal for providing a
+/sys like interface.  It has no internal buffering.  The means
+the daemon can not write until a client program is listening.
+Both named pipes and pseudo-ttys have internal buffers.

So what is wrong with internal buffers? Named pipes have been around for a long time, they should be able to be used much like this, right?

Buffers are great for streaming data but are unneeded for configuration and status information. Neither sysfs or procfs have internal buffers because they are not needed.

That's because they have a "consumer" at all times already, the kernel itself. And there is a buffer used, but it's quickly cleaned up.

Quoted 5 lines

In a way the problem is not the buffer itself but that a write
into a named pipe, for example, will succeed even if there is no one at the other end to receive the data. I think you'd want an open and write on a device driver to fail if the driver is not there and ready for the request.

Yes, but you aren't a device driver, you are a IPC between userspace processes.

Quoted 10 lines
Quoted 4 lines

Adding a new IPC function to the kernel should not be burried down in drivers/char/. We have 10+ different IPC mechanisms already, some simple, some more complex. Are you _sure_ none of the existing ones will not work for you?

I'm convinced this has the fewest lines of new code and the smallest impact on the rest of the system, but I could be wrong. The minimum feature set I want is to emulate for my user-space device driver what the kernel has for procfs and sysfs, That is,
echo 1 > /proc/sys/net/ipv4/ip_forward # procfs
echo 75 > /dev/motors/left/speed # proxy dev

As I mentioned above, the kernel does have buffers, and you are using them to talk to the device / driver / hardware / kernel when accessing proc and sysfs files.

Quoted 7 lines
Quoted 3 lines

Maybe a simple userspace library that wraps the
existing mechanisms would be better (no kernel changes needed, portable to any kernel release, etc.)?

Yes, this is the traditional model for approaching problems like the one I have. It would involve opening a unix socket, defining a protocol for that socket, and then writing several bindings for that protocol for different languages. Wow, that is a LOT of work.

Use protobufs, all of the bindings and protocol is already handled for you.

Quoted 4 lines

Luckily for us the procfs and sysfs authors have given us a much
better model to use: ASCII characters terminated by a newline. My Raspberry Pi customers expect to control an LED with a command like
this: echo 1 > /sys/class/gpio/gpio25

That is because you are talking to a hardware device, so that makes sense.

Quoted 3 lines

So it is entirely reasonable on their part to want to control a stepper motor with a command like this:
echo 300 > /dev/robot/stepper0/count

That would be good, if you were talking to hardware. But you aren't, you are talking to another userspace process "somewhere else".

thanks,

greg k-h

author
#8 lore raw

Greg
Thanks for discussing the module with me. I think I'm now closer to distilling it down to its essence.

GOAL:
The goal of this module is to give user space programs an interface similar to that enjoyed by the kernel using procfs and sysfs. All of the following should be possible
echo 1 > /proc/sys/net/ipv4/ip_forward # procfs
echo 75 > /dev/motors/left/speed # proxy
echo 5 > /dev/wpa_supplicant/use_channel # proxy

IPC:
To accomplish the above goal a new IPC is required. This new IPC must have the following characteristics:
- bidirectional
- writer blocks until reader is present
- a writer can cause the reader to close
- works with 'echo' and 'cat'

No existing IPC in Linux has all of these characteristics but proxy, the tiny self-contained module submitted, does. (Greg, I'm kind of surprised that a shim of an IPC like this wasn't added to Linux a long, long time ago.)

USE CASES:
Proxy should be added to the kernel because it can greatly improve Linux in two significant ways.

USE CASE #1: User space device drivers
A viable approach to user space device drivers would make life easier for both programmers and kernel maintainers. The latter because now a maintainer can now reasonably say
"go use proxy and a user space driver". Some of the SPI
and I2C drivers might have been easier to do with proxy.
Programmers doing device drivers might have an easier time
since it will be easier to prototype and debug a system in user space. SPI and I2C driver writers in particular may appreciate the ability to build a working system without having to go through the sometimes tedious process of a kernel submission.
Finally, some device drivers that are not possible today
would become possible. In my case I have a USB-serial link to a robot controller and so need a user space daemon to terminate the serial line. It is only with proxy that I can hide the details of this and give users a nice /dev view of the robot.

USE CASE #2: End the madness of language bindings Over 10 years ago kernel developers had the sense to escape (some) ioctl language bindings with the introduction of
procfs. How is it that in all this time we haven't done
the same thing for all the daemons that populate Linux? No, today daemon writers are still being forced to open a socket, define and document a protocol over it, and then write a library for that protocol for all the popular
languages. And we're not talking about just one or two
languages. No, now it more like C, Java, Python, PHP, and soon node.js. Next week some new language will wander off the street and need a yet another binding. Eeeech!
Let's let daemons use the same kind of interface that the
kernel has with /sys and /proc. With proxy, daemon coders could define an ASCII interface in exactly the same way the kernel has. The inclusion of 'echo' and 'cat' above is kind of a litmus test. If a daemon interface works with cat and echo, it will _NEVER_ need dedicated per-language bindings.

thanks
Bob Smith

#9 lore raw
Quoted 5 lines · Bob Smith

Greg
Thanks for discussing the module with me. I think I'm now closer to distilling it down to its essence.

Quoted 7 lines

GOAL:
The goal of this module is to give user space programs an interface similar to that enjoyed by the kernel using procfs and sysfs. All of the following should be possible
echo 1 > /proc/sys/net/ipv4/ip_forward # procfs
echo 75 > /dev/motors/left/speed # proxy
echo 5 > /dev/wpa_supplicant/use_channel # proxy

No it shouldn't, that is userspace talking to the kernel, you aren't doing that at all.

Quoted 7 lines

IPC:
To accomplish the above goal a new IPC is required. This new IPC must have the following characteristics:
- bidirectional
- writer blocks until reader is present
- a writer can cause the reader to close
- works with 'echo' and 'cat'

Who is saying "must" here? Why are those requirements at all?

Quoted 9 lines

No existing IPC in Linux has all of these characteristics but proxy, the tiny self-contained module submitted, does. (Greg, I'm kind of surprised that a shim of an IPC like this wasn't added to Linux a long, long time ago.)

USE CASES:
Proxy should be added to the kernel because it can greatly improve Linux in two significant ways.

Quoted 6 lines

USE CASE #1: User space device drivers
A viable approach to user space device drivers would make life easier for both programmers and kernel maintainers. The latter because now a maintainer can now reasonably say
"go use proxy and a user space driver". Some of the SPI
and I2C drivers might have been easier to do with proxy.

Specifically how would someone would use this to write a userspace driver? I'm totally not seeing it at all, and possibly, that's why I am so confused.

Quoted 6 lines

Programmers doing device drivers might have an easier time
since it will be easier to prototype and debug a system in user space. SPI and I2C driver writers in particular may appreciate the ability to build a working system without having to go through the sometimes tedious process of a kernel submission.

"tedious"? Those crummy kernel maintainers, always insisting on the highest quality of code, it's as if the product runs the world or something. Oh wait...

Quoted 6 lines

Finally, some device drivers that are not possible today
would become possible. In my case I have a USB-serial link to a robot controller and so need a user space daemon to terminate the serial line. It is only with proxy that I can hide the details of this and give users a nice /dev view of the robot.

How specifically would you do this with such a usb-serial device?

Quoted 4 lines

USE CASE #2: End the madness of language bindings Over 10 years ago kernel developers had the sense to escape (some) ioctl language bindings with the introduction of
procfs. How is it that in all this time we haven't done

Quoted 8 lines

the same thing for all the daemons that populate Linux? No, today daemon writers are still being forced to open a socket, define and document a protocol over it, and then write a library for that protocol for all the popular
languages. And we're not talking about just one or two
languages. No, now it more like C, Java, Python, PHP, and soon node.js. Next week some new language will wander off the street and need a yet another binding. Eeeech!

The kernel doesn't deal with language bindings, it provides a syscall interface that any language can call, or not, it's up to them. So this really isn't relevant at all.

Quoted 6 lines

Let's let daemons use the same kind of interface that the
kernel has with /sys and /proc. With proxy, daemon coders could define an ASCII interface in exactly the same way the kernel has. The inclusion of 'echo' and 'cat' above is kind of a litmus test. If a daemon interface works with cat and echo, it will _NEVER_ need dedicated per-language bindings.

ASCII isn't all that its cracked up to be, you should know better than that :)

And why ASCII? Why not XML? :)

specific examples please,

greg k-h

author
#10 lore raw

Greg
This sample program shows what I'm trying to accomplish.

I still owe you a reply for your previous posting

thanks
Bob Smith

/*
* pxtest.c : This program demonstrates the use of a proxy device. *
* The program generates some data once a second and tries to send
* it to /dev/proxyout. The original data is modified by adding
* an offset to each input character. The offset can be set or
* viewed at the proxy device node /dev/proxyctrl.
*
* Typical usage might be

 *    sudo modprobe proxy
 *    PROXYDEV=`grep proxy /proc/devices | cut -d\  -f 1`
 *    sudo mknod /dev/proxyout c $PROXYDEV 0
 *    sudo mknod /dev/proxyctrl c $PROXYDEV 1
 *    sudo chmod 666 /dev/proxyout /dev/proxyctrl
 *    gcc -o pxtest pxtest.c
 *    ./pxtest &
 *    cat /dev/proxyout    # view the output
 *    (switch to another terminal window)
 *    cat /dev/proxyctrl   # what is the offset?
 *    echo 2 > /dev/proxyctrl  # set offset to 2

*/

#include <stdio.h>
#include <stdlib.h>
#include <termio.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include <sys/fcntl.h>
#include <sys/time.h>

extern int errno;
#define PXBUFZS 100

int main (int argc, char *argv[])

{
    fd_set rfds;                /* for select() */
    fd_set wfds;                /* for select() */
    int    nfds;                /* for select() */
    struct timeval tv;          /* for select() */
    time_t now;                 /* source of input data */
    int    i;
    int    offset = 0;          /* configured via /dev/proxyctrl */
    int    outfd;               /* fd to /dev/proxyout */
    char   obuff[PXBUFZS];
    int    listener;            /* ==1 if someone is listening at /dev/proxyout */
    int    ctrlfd = -1;         /* fd to /dev/proxyctrl */
    char   cbuff[PXBUFZS];      /* i/o buffer for /dev/proxyctrl */
    int    slret,wrret,rdret;   /* select() write() read() return value */


    outfd =  open("/dev/proxyout", (O_WRONLY | O_NDELAY) , 0);
    if (outfd < 0 ) {
        printf("Unable to open proxy output port\n");
        exit(1);
    }
    listener = 0;

    tv.tv_sec = 1;
    tv.tv_usec = 0;

    while(1) {
        FD_ZERO(&rfds);
        FD_ZERO(&wfds);

        /* open, or reopen, the offset control port at /dev/proxyctrl */
        if (ctrlfd == -1) {
            ctrlfd =  open("/dev/proxyctrl", O_RDWR | O_NDELAY,0);
            if (ctrlfd < 0 ) {
                printf("Unable to open proxy control port\n");
                exit(1);
            }
        }
        FD_SET(ctrlfd, &rfds);
        FD_SET(ctrlfd, &wfds);

        /* If no one is listening, watch for a connection */
        if (listener == 0) {
            FD_SET(outfd, &wfds);
        }

        nfds = (outfd > ctrlfd) ? outfd : ctrlfd;

        slret = select((nfds + 1), &rfds, &wfds, (fd_set *)NULL, &tv);

        if (slret == 0) {
            /* Generate bogus data.  Real data might be coming from
             * an I2C read or from an accelerometer at the end of a
             * USB serial link.  For now, just use the current time */
            time(&now);
            ctime_r(&now, obuff);

            /* "process" the data by adding offset to each character */
            i = 0;
            while (obuff[i] != '\n') {
                obuff[i] = (char) (obuff[i] + offset);
                obuff[i] = (isprint(obuff[i])) ? obuff[i] : '_';
                i++;
            }

            /* Try to send the processed output to /dev/proxyout if possible */
            if (listener == 1) {
                wrret = write(outfd, obuff, strlen(obuff));
                if ((wrret == 0) || ((wrret < 0) && (errno == EAGAIN))) {
                    /* listener dropped off */
                    listener = 0;
                }
            }
            tv.tv_sec = 1;
            tv.tv_usec = 0;
        }

        /* Did a listener attach at /dev/proxyout? */
        if (FD_ISSET(outfd, &wfds)) {
            listener = 1;
        }

        /* Data on /dev/proxyctrl is marshalled as newline terminated ASCII
         * This is not a requirement.  Use binary, XML or whatever you need.
         * This demo forces a close but that too is not required. */

        /* Did anyone ask to read the offset value? */
        if (FD_ISSET(ctrlfd, &wfds)) {
            snprintf(cbuff, PXBUFZS, "%d\n", offset);
            write(ctrlfd, cbuff, strlen(cbuff));  /* send offset value */
            write(ctrlfd, cbuff, 0);              /* send EOF */
        }

        /* Is anyone trying to set the offset value? */
        if (FD_ISSET(ctrlfd, &rfds)) {
            rdret = read(ctrlfd, cbuff, PXBUFZS);
            if (rdret == 0) {
                close(ctrlfd);
                ctrlfd = -1;
            } else if ((rdret > 0) && (cbuff[rdret - 1] == '\n')) {
                /* buffer mgmt should be more than checking for ending \n */
                sscanf(cbuff, "%d", &offset);
            }
        }
    }
}
#11 lore raw
Quoted 18 lines · Bob Smith

Greg
This sample program shows what I'm trying to accomplish.

I still owe you a reply for your previous posting

thanks
Bob Smith

/*
* pxtest.c : This program demonstrates the use of a proxy device. *
* The program generates some data once a second and tries to send
* it to /dev/proxyout. The original data is modified by adding
* an offset to each input character. The offset can be set or
* viewed at the proxy device node /dev/proxyctrl.
*
* Typical usage might be

Quoted 4 lines
 *    sudo modprobe proxy
 *    PROXYDEV=`grep proxy /proc/devices | cut -d\  -f 1`
 *    sudo mknod /dev/proxyout c $PROXYDEV 0
 *    sudo mknod /dev/proxyctrl c $PROXYDEV 1

No one should ever have to mknod a device node, the kernel should do this for us automatically, please don't regress to the 1990's...

Quoted 1 line

* sudo chmod 666 /dev/proxyout /dev/proxyctrl

That's mighty permissive :(

Quoted 7 lines
 *    gcc -o pxtest pxtest.c
 *    ./pxtest &
 *    cat /dev/proxyout    # view the output
 *    (switch to another terminal window)
 *    cat /dev/proxyctrl   # what is the offset?
 *    echo 2 > /dev/proxyctrl  # set offset to 2

*/

I really don't understand this, you just have two programs talking to each other, passing the data blindly through the kernel. Again, we already have over 10 different ways to do IPC these days, are you _sure_ that _none_ of them work for you like this? You have gone and looked at them all, right?

thanks,

greg k-h

author
#12 lore raw
Quoted 2 lines · Greg Kroah-Hartman
Quoted 1 line

* sudo chmod 666 /dev/proxyout /dev/proxyctrl

That's mighty permissive :(

For a demo it might be OK.

BUT: I think I should modify the module to forward a close request (write 0 bytes) only if the sender UID matched the proxy node's UID. This might not be strictly required but is a security nice to have.

Quoted 8 lines
Quoted 7 lines
  *    gcc -o pxtest pxtest.c
  *    ./pxtest &
  *    cat /dev/proxyout    # view the output
  *    (switch to another terminal window)
  *    cat /dev/proxyctrl   # what is the offset?
  *    echo 2 > /dev/proxyctrl  # set offset to 2

*/

Quoted 5 lines

I really don't understand this, you just have two programs talking to each other, passing the data blindly through the kernel. Again, we already have over 10 different ways to do IPC these days, are you _sure_ that _none_ of them work for you like this? You have gone and looked at them all, right?

All along I've had a clear goal. I want to configure a running program the same way I configure the kernel. It is simple and I don't need any language bindings.
cat /dev/proxyctrl # what is the offset?
echo 2 > /dev/proxyctrl # set offset to 2

Yes, I am sure that nothing else will do. A named pipe is the closest
but it has a buffer and is not bidirectional. I am also convinced that
there is no way to do what I want with fewer lines of code.

thanks
Bob Smith

#13 lore raw
Quoted 4 lines · Bob Smith
Quoted 2 lines · Greg Kroah-Hartman
Quoted 1 line

* sudo chmod 666 /dev/proxyout /dev/proxyctrl

That's mighty permissive :(

For a demo it might be OK.

You ignored my mknod comment.

Also, no, setting the permissions like this is not ok for a real system, what is going to be in charge of setting the permissions on these random device nodes?

greg k-h

#14 lore raw
In reply to Bob Smith
Quoted 24 lines · Bob Smith
Quoted 2 lines · Greg Kroah-Hartman
Quoted 1 line

* sudo chmod 666 /dev/proxyout /dev/proxyctrl

That's mighty permissive :(

For a demo it might be OK.

BUT: I think I should modify the module to forward a close request (write 0 bytes) only if the sender UID matched the proxy node's UID. This might not be strictly required but is a security nice to have.

Quoted 8 lines
Quoted 7 lines
 *    gcc -o pxtest pxtest.c
 *    ./pxtest &
 *    cat /dev/proxyout    # view the output
 *    (switch to another terminal window)
 *    cat /dev/proxyctrl   # what is the offset?
 *    echo 2 > /dev/proxyctrl  # set offset to 2

*/

Quoted 5 lines

I really don't understand this, you just have two programs talking to each other, passing the data blindly through the kernel. Again, we already have over 10 different ways to do IPC these days, are you _sure_ that _none_ of them work for you like this? You have gone and looked at them all, right?

Quoted 5 lines

All along I've had a clear goal. I want to configure a running program the same way I configure the kernel. It is simple and I don't need any language bindings.
cat /dev/proxyctrl # what is the offset?
echo 2 > /dev/proxyctrl # set offset to 2

You have language bindings right there in bash for this api, what you are saying is that you don't want to write new syscall bindings for new languages, which is fine, don't do that, use the ones we already have for the vast number of different IPC types.

Quoted 3 lines

Yes, I am sure that nothing else will do. A named pipe is the closest
but it has a buffer and is not bidirectional. I am also convinced that
there is no way to do what I want with fewer lines of code.

What is your specific requirements, I see you couch them in terms of what you have created, but none in terms of actual requirements with no specific implementation.

And all of my other outstanding questions still remain, please address those as well.

thanks,

greg k-h

author
#15 lore raw
Quoted 7 lines · Greg Kroah-Hartman
Quoted 2 lines

cat /dev/proxyctrl # what is the offset?
echo 2 > /dev/proxyctrl # set offset to 2

You have language bindings right there in bash for this api, what you are saying is that you don't want to write new syscall bindings for new languages, which is fine, don't do that, use the ones we already have for the vast number of different IPC types.

You are correct. There very much is a protocol in use. Just as there is for setting ip_forward in /proc. And from your previous comment, it doesn't have to be ASCII. It could be binary or XML.

Quoted 4 lines

What is your specific requirements, I see you couch them in terms of what you have created, but none in terms of actual requirements with no specific implementation.

You are correct. I have been giving them in terms of my goal. The title still captures it: "a simple device to give daemons a /sys-like interface".

I am not a kernel programmer. I am an Electrical Engineer trying to control a robot. So I don't know what you mean by "actual requirements"
or a "specific implementation". If you point me at a working example
I'll be happy to try to provide these.

Quoted 3 lines

And all of my other outstanding questions still remain, please address those as well.

Yes, understood.

Greg, once again let me thank you for your patience while dealing with an EE (who probably needs more adult supervision).

thanks
Bob Smith

#16 lore raw
Quoted 4 lines · Bob Smith
Quoted 3 lines · Greg Kroah-Hartman
Quoted 2 lines

cat /dev/proxyctrl # what is the offset?
echo 2 > /dev/proxyctrl # set offset to 2

Quoted 8 lines
Quoted 4 lines

You have language bindings right there in bash for this api, what you are saying is that you don't want to write new syscall bindings for new languages, which is fine, don't do that, use the ones we already have for the vast number of different IPC types.

You are correct. There very much is a protocol in use. Just as there is for setting ip_forward in /proc. And from your previous comment, it doesn't have to be ASCII. It could be binary or XML.

You are mixing protocols and bindings and system calls up it seems. They are not the same at all.

Quoted 7 lines
Quoted 3 lines

What is your specific requirements, I see you couch them in terms of what you have created, but none in terms of actual requirements with no specific implementation.

You are correct. I have been giving them in terms of my goal. The title still captures it: "a simple device to give daemons a /sys-like interface".

Again, /sys and /proc is talking to the kernel, not userspace to userspace, I still fail to understand how you will do that to create a "userspace" driver.

Quoted 4 lines

I am not a kernel programmer. I am an Electrical Engineer trying to control a robot. So I don't know what you mean by "actual requirements"
or a "specific implementation". If you point me at a working example
I'll be happy to try to provide these.

How can you control a robot with this code?

What do you want to do in order to control your robot? What are your needs in accessing the hardware? What hardware are you wanting to control? And why can't you just access that hardware through the normal kernel apis we have today?

thanks,

greg k-h

author
#17 lore raw

Greg Kroah-Hartman wrote:>

Quoted 8 lines

You are mixing protocols and bindings and system calls up it seems. They are not the same at all.

How can you control a robot with this code?
What do you want to do in order to control your robot? What are your needs in accessing the hardware? What hardware are you wanting to control? And why can't you just access that hardware through the normal kernel apis we have today?

Greg
I'll reply again to this message but for now let me try
another explanation that does not mention sysfs, procfs, or
device drivers. This is probably how I should have started.

=============================================================

proxy: a very lightweight alternative to FUSE

Proxy is a simple bidirectional character device that almost transparently proxies opens, reads, writes, and closes from one side of the device to the other side.

FUSE is great for giving applications a file system interface to an application's internal variables and values. If a FUSE application has an internal variable called "foo" then one way that variable could be exposed is with a (FUSE) file system entry. That is, reading and writing foo might appear as:
cat < /fuse_mp/foo
echo 5 > /fuse_mp/foo

An extraordinarily important, and often overlooked advantage of FUSE applications is that they almost never need language specific bindings. This is because every single programming language in Linux supports file IO. You don't need a binding to do something like this:

    open(/fuse_mp/foo)
    write(5\n)
    close

While the API offered by FUSE is nice and FUSE is really great for file systems, it has some severe limitations that may have prevented more widespread use. For most daemon developers the biggest limitation is that FUSE has its own main() routine. This makes it difficult or impossible use use FUSE as just an API in an application that requires select() and IO from other parts of the system.

Proxy solves this problem. Proxy is intended for application developers who would like to avoid writing many language specific binding but who, for one reason or another, can not use FUSE.

Proxy has two sides. One side remains open to clients (like the FUSE file system entries). The other side is connected to the application and can be tied into that application's select() (or other IO multiplexer in the case of node.js, for example). Just as with FUSE, it is entirely up to the application writer to format, and give syntax, and meaning to the data that passes through the proxy device.

Adding proxy to the kernel may make it easier for new types of daemons and services to appear in Linux since it can help remove the burden of writing language specific bindings for the daemon.

thanks
Bob Smith

#18 lore raw
Quoted 11 lines · Bob Smith

Greg Kroah-Hartman wrote:>

Quoted 8 lines

You are mixing protocols and bindings and system calls up it seems. They are not the same at all.

How can you control a robot with this code?
What do you want to do in order to control your robot? What are your needs in accessing the hardware? What hardware are you wanting to control? And why can't you just access that hardware through the normal kernel apis we have today?

Quoted 4 lines

Greg
I'll reply again to this message but for now let me try
another explanation that does not mention sysfs, procfs, or
device drivers. This is probably how I should have started.

I fail to understand how you will use this code to write a "userspace device driver" at all.

still confused,

greg k-h

author
#19 lore raw
Quoted 8 lines · Greg Kroah-Hartman
Quoted 4 lines · Bob Smith

Greg
I'll reply again to this message but for now let me try
another explanation that does not mention sysfs, procfs, or
device drivers. This is probably how I should have started.

I fail to understand how you will use this code to write a "userspace device driver" at all.

I just sent a message that cover userspace drivers. Basically, if you think userspace driver can exist, then you probably need something like this proxy driver.

thanks
Bob Smith

author
#20 lore raw
In reply to Greg Kroah-Hartman

Greg Kroah-Hartman wrote:
(snip)

Quoted 1 line

You are mixing protocols and bindings and system calls up it seems.> They are not the same at all.

Yes, I may be using the term binding wrong. As I understand it
- We should use a _syscall_ to open a unix socket on the daemon, then
- define a _protocol_ to describe the data flowing over the socket,
- a C _binding_ to present a C API and hide the protocol for C programmers,
- a C++ binding and API for C++ programmers
- a Java binding
- a PHP binding
- a Perl binding
- a Python binding
- a node.js binding
- a Scratch binding for Raspberry Pi users
- and some kind of shell binding for Bash programmers

Quoted 5 lines

(snip)
Again, /sys and /proc is talking to the kernel, not userspace to userspace, I still fail to understand how you will do that to create a "userspace" driver.

From a kernel developer's point of view the term "userspace driver" may seem like an oxymoron. By definition, all devices on the system have to be controlled by the kernel. All else is just userspace.

As an _opinion_ only, I think maybe userspace device drivers do exist. It refers to hardware that the kernel is not, and should not, be aware of. This hardware is not seen because it is at the end of some kind of communications channel like USB-serial or Ethernet. A developer might like to view that hardware as part of the overall system even if Linux and the CPU do not have direct access to it. A userspace driver looks something like this

	=(ProxyDevNode)====(daemon)===(CommChannel)===(hardware)

As an engineer, I can see that "userspace driver" might not make sense. As a marketing guy, I'm super-duper pleased to tell my customers "Yes, we support Linux. After all, we have Userspace Device Drivers!" :)

Quoted 6 lines

(snip)
How can you control a robot with this code? What do you want to do in order to control your robot? What are your needs in accessing the hardware? What hardware are you wanting to control?

In my message I said I was building a robot. While true, this gives the erroneous impression that it is just me for just one robot. In fact, I build and sell FPGA based robot controllers. It is my _customers_ who build and program the robots.

The descriptions below may be representative of others wanting to have userspace device drivers even though the descriptions are for my specific case.

My (hardware) has a Xilinx FPGA with connectors that goes out to eight peripheral cards. There are about thirty different peripheral cards available The FPGA has to be programmed for a specific peripheral mix, but it is pretty easy for a customer to request a new FPGA image for a new mix of cards. Inside the FPGA the peripherals are controlled by 8-bit registers on an internal address bus.

My (CommChannel) is an FTDI USB-serial interface. The protocol over the link consists of reads and writes to the 8-bit registers in the FPGA. Polling is not needed since the FPGA can automatically generate a read response packet when it needs to.

My (daemon) is passed which serial port to use. It establishes a link to the FPGA and then asks it for a list of its peripherals. Using this list it loads a shared object library for each different peripheral. The init in the library creates the device nodes needed by the driver (userspace driver, that is). When all the device nodes have been set up the daemon drops root permissions. The daemon does not need root permissions if the device nodes are set up in advance.
Once everything is set up the system becomes completely event
driven. Sensor reading are passed from the FPGA through the daemon and out to the device nodes, and configuration changes are passed from the device node out to the FPGA.

Quoted 3 lines

And why can't you just access that hardware through the normal kernel apis we have today?

Because the kernel doesn't even see the hardware I'm controlling.

Quoted 2 lines

greg k-h

Greg, sorry this message was so long, and thanks again for your patience.

Bob Smith

#21 lore raw
Quoted 6 lines · Bob Smith

Greg Kroah-Hartman wrote:
(snip)

Quoted 1 line

You are mixing protocols and bindings and system calls up it seems.> They are not the same at all.

Yes, I may be using the term binding wrong. As I understand it
- We should use a _syscall_ to open a unix socket on the daemon, then

If you want to use unix sockets, yes, do that. All languages have bindings for those syscalls.

Quoted 1 line

- define a _protocol_ to describe the data flowing over the socket,

Good protocols exist, look at protobufs from Google if you want to define your own. Never create your own protocol these days, it doesn't make sense, be it a text one or something else.

Quoted 9 lines

- a C _binding_ to present a C API and hide the protocol for C programmers,
- a C++ binding and API for C++ programmers
- a Java binding
- a PHP binding
- a Perl binding
- a Python binding
- a node.js binding
- a Scratch binding for Raspberry Pi users
- and some kind of shell binding for Bash programmers

All of those languages already support Linux syscalls, no need to create anything else.

Quoted 8 lines
Quoted 4 lines

(snip)
Again, /sys and /proc is talking to the kernel, not userspace to userspace, I still fail to understand how you will do that to create a "userspace" driver.

From a kernel developer's point of view the term "userspace driver" may seem like an oxymoron. By definition, all devices on the system have to be controlled by the kernel. All else is just userspace.

Not true at all, I know all about userspace drivers, look at the UIO code in the Linux kernel. It was created explicitly for this exact thing, and to prevent the myrads of broken implementations from being created again and again and again. Just use it if you wish to talk to your hardware directly, lots of people do so.

Quoted 8 lines

As an _opinion_ only, I think maybe userspace device drivers do exist. It refers to hardware that the kernel is not, and should not, be aware of. This hardware is not seen because it is at the end of some kind of communications channel like USB-serial or Ethernet. A developer might like to view that hardware as part of the overall system even if Linux and the CPU do not have direct access to it. A userspace driver looks something like this

Quoted 5 lines
	=(ProxyDevNode)====(daemon)===(CommChannel)===(hardware)

As an engineer, I can see that "userspace driver" might not make sense. As a marketing guy, I'm super-duper pleased to tell my customers "Yes, we support Linux. After all, we have Userspace Device Drivers!" :)

Not really, you are just using an IPC to talk to a "real" device driver.

Quoted 6 lines

My (hardware) has a Xilinx FPGA with connectors that goes out to eight peripheral cards. There are about thirty different peripheral cards available The FPGA has to be programmed for a specific peripheral mix, but it is pretty easy for a customer to request a new FPGA image for a new mix of cards. Inside the FPGA the peripherals are controlled by 8-bit registers on an internal address bus.

FPGAs are interesting things, people are creating "real" drivers for them (see the linux-kernel archives for a few examples.) Other people just use the UIO layer instead, which works quite well for them. I suggest you do the same thing.

Again, you are creating a new form of userspace/userspace IPC, without a good reason for why one of the existing IPC implementations will not work for you (no, being able to use "echo" is not a good reason, you can do that with local sockets just fine).

I suggest you take a look at the book, The Linux Programming Interface, by Michael Kerrisk, specifically chapter 43, which goes into great detail about all of the existing IPC mechanisms that Linux already provides. I'm sure one of them should be able to fit your needs.

Otherwise, to accept this code, I need to see a way that normal users can use it (i.e. no root or mknod), and that it can handle namespaces and the security interface that the kernel has to support. To do so otherwise would be unfair to users who expect such a thing.

thanks,

greg k-h

author
#22 lore raw
Quoted 3 lines · Greg Kroah-Hartman

Good protocols exist, look at protobufs from Google if you want to define your own. Never create your own protocol these days, it doesn't make sense, be it a text one or something else.

OK. I was using the term in the broader sense in which _meaning_ is assigned to the data in the protocol, not just the data marshaling.

Quoted 10 lines
Quoted 10 lines

- a C _binding_ to present a C API and hide the protocol for C programmers,
- a C++ binding and API for C++ programmers
- a Java binding
- a PHP binding
- a Perl binding
- a Python binding
- a node.js binding
- a Scratch binding for Raspberry Pi users
- and some kind of shell binding for Bash programmers

Quoted 2 lines

All of those languages already support Linux syscalls, no need to create anything else.

Yes, we can publish the protocol and let the application writer deal with it. Bindings are nice only if you want to give a simple API to the developer or want to hide the details of the protocol.

Quoted 10 lines
Quoted 4 lines

From a kernel developer's point of view the term "userspace driver"
may seem like an oxymoron. By definition, all devices on the system have to be controlled by the kernel. All else is just userspace.

Not true at all, I know all about userspace drivers, look at the UIO code in the Linux kernel. It was created explicitly for this exact thing, and to prevent the myrads of broken implementations from being created again and again and again. Just use it if you wish to talk to your hardware directly, lots of people do so.

Well, not this exact thing. UIO is great if your hardware hangs on a bus directly connected to the CPU. It does nothing to help the case of hardware connected over some communications link.

Quoted 9 lines
Quoted 9 lines

As an _opinion_ only, I think maybe userspace device drivers do exist. It refers to hardware that the kernel is not, and should not, be aware of. This hardware is not seen because it is at the end of some kind of communications channel like USB-serial or Ethernet. A developer might like to view that hardware as part of the overall system even if Linux and the CPU do not have direct access to it. A userspace driver looks something like this

Quoted 3 lines
Quoted 1 line
	=(ProxyDevNode)====(daemon)===(CommChannel)===(hardware)

Not really, you are just using an IPC to talk to a "real" device driver.

Yes, each of the "=" above has data passing through a real driver.

Quoted 5 lines

FPGAs are interesting things, people are creating "real" drivers for them (see the linux-kernel archives for a few examples.) Other people just use the UIO layer instead, which works quite well for them. I suggest you do the same thing.

UIO can not see hardware at the end of a USB-serial link.

Quoted 10 lines

Again, you are creating a new form of userspace/userspace IPC, without a good reason for why one of the existing IPC implementations will not work for you (no, being able to use "echo" is not a good reason, you can do that with local sockets just fine).

I suggest you take a look at the book, The Linux Programming Interface, by Michael Kerrisk, specifically chapter 43, which goes into great detail about all of the existing IPC mechanisms that Linux already provides. I'm sure one of them should be able to fit your needs.

Quoted 4 lines · Greg Kroah-Hartman

Otherwise, to accept this code, I need to see a way that normal users can use it (i.e. no root or mknod), and that it can handle namespaces and the security interface that the kernel has to support. To do so otherwise would be unfair to users who expect such a thing.

OK, this makes sense.

thanks
Bob Smith

#23 lore raw
Quoted 7 lines · Bob Smith
Quoted 3 lines · Greg Kroah-Hartman

Good protocols exist, look at protobufs from Google if you want to define your own. Never create your own protocol these days, it doesn't make sense, be it a text one or something else.

OK. I was using the term in the broader sense in which _meaning_ is assigned to the data in the protocol, not just the data marshaling.

Again, protobufs are a great way to define the meaning of the protocol in a manner that is descriptive, fast, versioned, discoverable, and best of all for you, with bindings for all languages :)

Quoted 8 lines
Quoted 5 lines

Not true at all, I know all about userspace drivers, look at the UIO code in the Linux kernel. It was created explicitly for this exact thing, and to prevent the myrads of broken implementations from being created again and again and again. Just use it if you wish to talk to your hardware directly, lots of people do so.

Well, not this exact thing. UIO is great if your hardware hangs on a bus directly connected to the CPU. It does nothing to help the case of hardware connected over some communications link.

Like PCI? :)

Actually, I'm not kidding about that, I have a PCI bus here that is across a flexible cable that can dynamically be plugged and unplugged from a machine at any point in time using a communications link. It's called Thunderbolt today, but has been called ExpressBus, and lots of other names in the past.

Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

As an _opinion_ only, I think maybe userspace device drivers do exist. It refers to hardware that the kernel is not, and should not, be aware of. This hardware is not seen because it is at the end of some kind of communications channel like USB-serial or Ethernet. A developer might like to view that hardware as part of the overall system even if Linux and the CPU do not have direct access to it. A userspace driver looks something like this

Quoted 5 lines
Quoted 3 lines
Quoted 1 line
	=(ProxyDevNode)====(daemon)===(CommChannel)===(hardware)

Not really, you are just using an IPC to talk to a "real" device driver.

Yes, each of the "=" above has data passing through a real driver.

No it doesn't. A "real" driver talks to hardware. You only have that for the last "===".

Quoted 6 lines
Quoted 4 lines

FPGAs are interesting things, people are creating "real" drivers for them (see the linux-kernel archives for a few examples.) Other people just use the UIO layer instead, which works quite well for them. I suggest you do the same thing.

UIO can not see hardware at the end of a USB-serial link.

Nor should it ever be used for something like that. There is a protocol for this device that the kernel exposes, use it :)

thanks,

greg k-h

author
#24 lore raw
In reply to Greg Kroah-Hartman
Quoted 4 lines · Greg Kroah-Hartman

Otherwise, to accept this code, I need to see a way that normal users can use it (i.e. no root or mknod), and that it can handle namespaces and the security interface that the kernel has to support. To do so otherwise would be unfair to users who expect such a thing.

Greg, I don't know the etiquette of the lkml but I think the above means "no, go away".

OK.
On my way out the door I'll give a recap and say thanks

GOAL
The goal of this patch was to make it possible to configure daemons using simple file IO. The litmus test for this is that commands like these should be possible
cat < /var/daemons/wpa_supplicant/use_channel echo 5 >/var/daemons/wpa_supplicant/use_channel

Yes, there are many other ways to configure a daemon but none with the simplicity and grace of file IO. For proof of this I point to procfs and sysfs.

APPROACHES
Modifying name pipes was rejected as being too complex. Modifying FUSE was rejected for the amount of effort needed. The method chosen was to create a small character device to pass the data between the client and the daemon. The resulting code was small and simple but requires a device node.

CONCLUSION
Pseudo-ttys not withstanding, the kernel does not want IPC mechanisms that require root privileges or mknod. For this and other reasons this patch is rejected.

Greg, once again thanks for your patience in helping a non-kernel guy through all of this. Thanks.

bye
Bob Smith

#25 lore raw
Quoted 34 lines · Bob Smith
Quoted 5 lines · Greg Kroah-Hartman

Otherwise, to accept this code, I need to see a way that normal users can use it (i.e. no root or mknod), and that it can handle namespaces and the security interface that the kernel has to support. To do so otherwise would be unfair to users who expect such a thing.

Greg, I don't know the etiquette of the lkml but I think the above means "no, go away".

OK.
On my way out the door I'll give a recap and say thanks

GOAL
The goal of this patch was to make it possible to configure daemons using simple file IO. The litmus test for this is that commands like these should be possible
cat < /var/daemons/wpa_supplicant/use_channel echo 5 >/var/daemons/wpa_supplicant/use_channel

Yes, there are many other ways to configure a daemon but none with the simplicity and grace of file IO. For proof of this I point to procfs and sysfs.

APPROACHES
Modifying name pipes was rejected as being too complex. Modifying FUSE was rejected for the amount of effort needed. The method chosen was to create a small character device to pass the data between the client and the daemon. The resulting code was small and simple but requires a device node.

Quoted 8 lines

CONCLUSION
Pseudo-ttys not withstanding, the kernel does not want IPC mechanisms that require root privileges or mknod. For this and other reasons this patch is rejected.

Greg, once again thanks for your patience in helping a non-kernel guy through all of this. Thanks.

/me read the whole thread and still does get why you can't use CUSE. ...or AF_UNIX.

If you really have an use case which is not covered by CUSE, please fix CUSE.

Quoted 8 lines

bye
Bob Smith

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

Signature · 2 lines
Thanks,
//richard
author
#26 lore raw
Quoted 7 lines · richard -rw- weinberger
Quoted 7 lines

GOAL
The goal of this patch was to make it possible to configure daemons using simple file IO. The litmus test for this is that commands like these should be possible
cat < /var/daemons/wpa_supplicant/use_channel echo 5 >/var/daemons/wpa_supplicant/use_channel

Quoted 6 lines
Quoted 3 lines

Yes, there are many other ways to configure a daemon but none with the simplicity and grace of file IO. For proof of this I point to procfs and sysfs.

/me read the whole thread and still does get why you can't use CUSE. ...or AF_UNIX.

Rightly or wrongly, my goal is pretty clear. I want to be able to use file IO to control a daemon. AF_UNIX doesn't help. CUSE/FUSE takes over main() and makes it very difficult to use select() and file descriptors. So it fails too for now.

Quoted 2 lines

If you really have an use case which is not covered by CUSE, please fix CUSE.

Yeah, if I proceed from here then modifying the user space parts of FUSE might be the best way to go.

Sorry that it took so long to get to the point that my goals for the patch were clearly stated. As I say, I'm an EE who probably need more adult supervision. :)

thanks
Bob Smith

maintainer
#27 lore raw
In reply to Bob Smith
Quoted 10 lines · Bob Smith

GOAL
The goal of this patch was to make it possible to configure daemons using simple file IO. The litmus test for this is that commands like these should be possible
cat < /var/daemons/wpa_supplicant/use_channel echo 5 >/var/daemons/wpa_supplicant/use_channel

Yes, there are many other ways to configure a daemon but none with the simplicity and grace of file IO. For proof of this I point to procfs and sysfs.

I'll try to keep out of the discussion about whether or not another IPC mechanism with your desired semantics would be good to have in the kernel, but one comment about implementing it:

If you want to have that behavior, I think the best way to do it would be new file system that combines aspects of tmpfs and debugfs, letting users with write access to the mount point (or a directory under it) create subdirectories and files using regular unix permission handling. You would then always use the file_operations that you defined for your chardev but use that with inode_operations similar to tmpfs.

Arnd

author
#28 lore raw
Quoted 7 lines · Arnd Bergmann
Quoted 6 lines

GOAL
The goal of this patch was to make it possible to configure daemons using simple file IO. The litmus test for this is that commands like these should be possible
cat < /var/daemons/wpa_supplicant/use_channel echo 5 >/var/daemons/wpa_supplicant/use_channel

Quoted 7 lines

If you want to have that behavior, I think the best way to do it would be new file system that combines aspects of tmpfs and debugfs, letting users with write access to the mount point (or a directory under it) create subdirectories and files using regular unix permission handling. You would then always use the file_operations that you defined for your chardev but use that with inode_operations similar to tmpfs.

THANKS! It would still be a kernel patch and still require root to set up but so would FUSE and your approach might be much lighter weight.

thanks
Bob Smith

maintainer
#29 lore raw
Quoted 16 lines · Bob Smith
Quoted 7 lines · Arnd Bergmann
Quoted 6 lines

GOAL
The goal of this patch was to make it possible to configure daemons using simple file IO. The litmus test for this is that commands like these should be possible
cat < /var/daemons/wpa_supplicant/use_channel echo 5 >/var/daemons/wpa_supplicant/use_channel

Quoted 7 lines

If you want to have that behavior, I think the best way to do it would be new file system that combines aspects of tmpfs and debugfs, letting users with write access to the mount point (or a directory under it) create subdirectories and files using regular unix permission handling. You would then always use the file_operations that you defined for your chardev but use that with inode_operations similar to tmpfs.

Quoted 3 lines

THANKS! It would still be a kernel patch and still require root to set up but so would FUSE and your approach might be much lighter weight.

Correct. Of course the only need for root access is to set up the fstab entry for the file system, which is not all that different from allowing fuse user mounts.

Arnd

author
#30 lore raw
In reply to Greg Kroah-Hartman
Quoted 1 line · Greg Kroah-Hartman

You ignored my mknod comment.

Yes, proxy is a type of IPC. It's closest counterpart in the
kernel now is a named pipe. The kernel does not try to create
named pipes automatically. Named pipes are created deliberately by users with the mkfifo command or system call. Same with proxy. The proxy device nodes are application specific and need to be created as needed by applications.

Allocation of minor numbers is an issue but that is an issue that is separate from the proxy module itself.

Quoted 3 lines

Also, no, setting the permissions like this is not ok for a real system, what is going to be in charge of setting the permissions on these random device nodes?

Again, compare proxy to a named pipe. It is up the application writer to decide who gets read and write access to its proxy nodes.

thanks
Bob Smith

#31 lore raw
Quoted 8 lines · Bob Smith
Quoted 1 line · Greg Kroah-Hartman

You ignored my mknod comment.

Yes, proxy is a type of IPC. It's closest counterpart in the
kernel now is a named pipe. The kernel does not try to create
named pipes automatically. Named pipes are created deliberately by users with the mkfifo command or system call. Same with proxy. The proxy device nodes are application specific and need to be created as needed by applications.

But applications do not have the permissions in a system to create device nodes. Nor should they need that permission.

Quoted 2 lines

Allocation of minor numbers is an issue but that is an issue that is separate from the proxy module itself.

How is it separate, it seems tied directly to it as something that must be handled properly.

Quoted 6 lines
Quoted 3 lines

Also, no, setting the permissions like this is not ok for a real system, what is going to be in charge of setting the permissions on these random device nodes?

Again, compare proxy to a named pipe. It is up the application writer to decide who gets read and write access to its proxy nodes.

Ok, but to do so, you have to have root permissions to start with, which is generally not going to happen on sane systems. Only allowing root access to this seems like a huge limitation.

thanks,

greg k-h

author
#32 lore raw
Quoted 5 lines · Greg Kroah-Hartman
Quoted 2 lines

The proxy device nodes are application specific and need to be created as needed by applications.

But applications do not have the permissions in a system to create device nodes. Nor should they need that permission.

Agreed. But you need root permissions to install an application and part of that installation can be setting up systemd files
that allocate resources at boot. Also, some applications start
as root just so they can do this kind of allocation. The app can (and should) drop root privileges when it can.

Quoted 5 lines
Quoted 3 lines

Allocation of minor numbers is an issue but that is an issue that is separate from the proxy module itself.

How is it separate, it seems tied directly to it as something that must be handled properly.

It can, but does not need to be handled in the kernel. It could be handled in user space.

Quoted 11 lines
Quoted 7 lines
Quoted 4 lines

Also, no, setting the permissions like this is not ok for a real system, what is going to be in charge of setting the permissions on these random device nodes?

Again, compare proxy to a named pipe. It is up the application writer to decide who gets read and write access to its proxy nodes.

Ok, but to do so, you have to have root permissions to start with, which is generally not going to happen on sane systems. Only allowing root access to this seems like a huge limitation.

As noted above, yes, root has to set it up and set the permissions, but this is hardly unusual, is it?

thanks
Bob Smith

#33 lore raw
Quoted 10 lines · Bob Smith
Quoted 5 lines · Greg Kroah-Hartman
Quoted 2 lines

The proxy device nodes are application specific and need to be created as needed by applications.

But applications do not have the permissions in a system to create device nodes. Nor should they need that permission.

Agreed. But you need root permissions to install an application and part of that installation can be setting up systemd files that allocate resources at boot.

Do you have examples of those systemd files? Last I looked, they didn't have mknod permissions anymore, which is a good thing.

Quoted 3 lines

Also, some applications start as root just so they can do this kind of allocation. The app can (and should) drop root privileges when it can.

You shouldn't require root for a new feature, that seems strange.

Also, namespaces aren't addressed at all, but that's a totally different issue...

Quoted 15 lines
Quoted 4 lines
Quoted 2 lines

Allocation of minor numbers is an issue but that is an issue that is separate from the proxy module itself.

How is it separate, it seems tied directly to it as something that must be handled properly.

It can, but does not need to be handled in the kernel. It could be handled in user space.

Quoted 8 lines
Quoted 7 lines
Quoted 4 lines

Also, no, setting the permissions like this is not ok for a real system, what is going to be in charge of setting the permissions on these random device nodes?

Again, compare proxy to a named pipe. It is up the application writer to decide who gets read and write access to its proxy nodes.

Quoted 6 lines
Quoted 3 lines

Ok, but to do so, you have to have root permissions to start with, which is generally not going to happen on sane systems. Only allowing root access to this seems like a huge limitation.

As noted above, yes, root has to set it up and set the permissions, but this is hardly unusual, is it?

Yes it is, modern userspace does not create any device nodes anymore, please let's not regress on that point.

thanks,

greg k-h

author
#34 lore raw
Quoted 7 lines · Greg Kroah-Hartman
Quoted 3 lines · Bob Smith

Agreed. But you need root permissions to install an application and part of that installation can be setting up systemd files that allocate resources at boot.

Do you have examples of those systemd files? Last I looked, they didn't have mknod permissions anymore, which is a good thing.

The difference is that Linux usually detects the hardware that is connected to it and automatically creates device nodes for it. This is part of the boot process.
In the case of a userspace device driver, the kernel never sees
the hardware so it is up the USD to create the nodes for the hardware.

Quoted 5 lines
Quoted 4 lines

Also, some applications start as root just so they can do this kind of allocation. The app can (and should) drop root privileges when it can.

You shouldn't require root for a new feature, that seems strange.

OK, but root for a new feature dealing with hardware seems OK.

Quoted 3 lines

Also, namespaces aren't addressed at all, but that's a totally different issue...

No, but I hope namespace policy can be handled in userspace and not in the proxy module itself.

Quoted 7 lines

(snip)

Quoted 2 lines

As noted above, yes, root has to set it up and set the permissions, but this is hardly unusual, is it?

Yes it is, modern userspace does not create any device nodes anymore, please let's not regress on that point.

Yes, I suppose this can be viewed as a regression, but I don't see a way around this right now. The problem is that only the userspace driver sees the new hardware and so knows what device nodes to create.

Once again, thanks.

Bob Smith

#35 lore raw
Quoted 6 lines · Bob Smith
Quoted 5 lines · Greg Kroah-Hartman
Quoted 3 lines · Bob Smith

Agreed. But you need root permissions to install an application and part of that installation can be setting up systemd files that allocate resources at boot.

Quoted 8 lines
Quoted 2 lines

Do you have examples of those systemd files? Last I looked, they didn't have mknod permissions anymore, which is a good thing.

The difference is that Linux usually detects the hardware that is connected to it and automatically creates device nodes for it. This is part of the boot process.
In the case of a userspace device driver, the kernel never sees
the hardware so it is up the USD to create the nodes for the hardware.

Again, this isn't about hardware, it's about an ipc that you are creating for user to user communication. For this to require root access isn't acceptable.

Quoted 6 lines
Quoted 4 lines
Quoted 3 lines

Also, some applications start as root just so they can do this kind of allocation. The app can (and should) drop root privileges when it can.

You shouldn't require root for a new feature, that seems strange.

OK, but root for a new feature dealing with hardware seems OK.

But you are NOT dealing with hardware here (well, your specific implementation just happens to do so, but the driver sure doesn't.)

Also, root for hardware is not ok, otherwise how would you as a user be able to talk to your serial port, or filesystem.

Quoted 5 lines
Quoted 2 lines

Also, namespaces aren't addressed at all, but that's a totally different issue...

No, but I hope namespace policy can be handled in userspace and not in the proxy module itself.

How would that work out?

Quoted 10 lines
Quoted 6 lines

(snip)

Quoted 2 lines

As noted above, yes, root has to set it up and set the permissions, but this is hardly unusual, is it?

Yes it is, modern userspace does not create any device nodes anymore, please let's not regress on that point.

Yes, I suppose this can be viewed as a regression, but I don't see a way around this right now. The problem is that only the userspace driver sees the new hardware and so knows what device nodes to create.

Again, there is no "hardware" in your driver, that just happens to be how you are using this IPC. I could be using "hardware" for a daemon that talks over a named pipe, but that doesn't mean anything to the kernel code, right?

thanks,

greg k-h

author
#36 lore raw
In reply to Greg Kroah-Hartman
Quoted 5 lines · Greg Kroah-Hartman
Quoted 3 lines

echo 1 > /proc/sys/net/ipv4/ip_forward # procfs
echo 75 > /dev/motors/left/speed # proxy
echo 5 > /dev/wpa_supplicant/use_channel # proxy

No it shouldn't, that is userspace talking to the kernel, you aren't doing that at all.

You are correct. But it's not _what_ is being done, it's _how_. Procfs clients have a really simple way of sending data to the kernel

	open(ip_forward)
	write("1\n")
	close
I want the same thing for my user space daemon
	open(speed)
	write("75\n")
	close
Quoted 7 lines
Quoted 6 lines

new IPC must have the following characteristics:
- bidirectional
- writer blocks until reader is present
- a writer can cause the reader to close
- works with 'echo' and 'cat'

Who is saying "must" here? Why are those requirements at all?

I could be wrong but to accomplish an open/write/close interface sort of like sysfs or procfs, I think we need an IPC that is
- visible as a file name
- bidirectional
- both ends much be connected to communicate
- a writer can effectively send EOF through the device

Quoted 4 lines

Specifically how would someone would use this to write a userspace driver? I'm totally not seeing it at all, and possibly, that's why I am so confused.

Hopefully the sample program I sent earlier makes sense. The source of data in the sample program was time of day but it could have as easily been date from a USB serial device or from a generic i2c device.

Quoted 8 lines
Quoted 7 lines

Finally, some device drivers that are not possible today
would become possible. In my case I have a USB-serial link to a robot controller and so need a user space daemon to terminate the serial line. It is only with proxy that I can hide the details of this and give users a nice /dev view of the robot.

How specifically would you do this with such a usb-serial device?

Again, I hope the sample program makes this easier to see.

Quoted 5 lines
Quoted 2 lines

USE CASE #2: End the madness of per-language bindings

The kernel doesn't deal with language bindings, it provides a syscall interface that any language can call, or not, it's up to them. So this really isn't relevant at all.

Agreed. But isn't every IPC or other feature in the kernel there because someone in user space needed it? I hope so.

Quoted 4 lines

ASCII isn't all that its cracked up to be, you should know better than that :)
And why ASCII? Why not XML? :)

You are entirely correct here.

thanks
Bob Smith