* [PATCH 001/001] CHAR DRIVERS: a simple device to give daemons a /sys-like interface
[not found] <51FC5478.40500@linuxtoys.org>
@ 2013-08-03 1:19 ` Bob Smith
2013-08-03 1:56 ` Joe Perches
` (2 more replies)
0 siblings, 3 replies; 36+ messages in thread
From: Bob Smith @ 2013-08-03 1:19 UTC (permalink / raw)
To: Arnd Bergmann, Greg Kroah-Hartman; +Cc: linux-kernel
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 <bsmith@linuxtoys.org>
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
diff --git a/Documentation/proxy.txt b/Documentation/proxy.txt
new file mode 100644
index 0000000..6b9206a
--- /dev/null
+++ b/Documentation/proxy.txt
@@ -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.
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 1421997..d21ea1d 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -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
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 7ff1d0d..7009038 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -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/
diff --git a/drivers/char/proxy.c b/drivers/char/proxy.c
new file mode 100644
index 0000000..e56fa65
--- /dev/null
+++ b/drivers/char/proxy.c
@@ -0,0 +1,539 @@
+/*
+ * proxy.c: A bidirectional pipe device
+ *
+ * This device is meant as a simple proxy to connect two user-space
+ * programs through a device, allowing each of the user space programs
+ * to select() on the device. The first program to open the device gets
+ * immediately blocked on either reads or writes until the other side is
+ * opened. The idea of "two sides" is enforced by limiting the number
+ * of opens on the device to two.
+ * This device is different from named pipes and pseudo terminals in
+ * that it is bidirectional and it doesn't block writes when the buffer
+ * is full, it blocks when the buffer is full _OR_ if other end is closed.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of Version 2 of the GNU General Public License as
+ * published by the Free Software Foundatio
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc. ; 51 Franklin Street, Fifth Floor ; Boston, MA 02110-1301 ; USA
+ *
+ *
+ * Copyright (C) 2013 Demand Peripherals, Inc.
+ *
+ * Initial release: Bob Smith
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <linux/cdev.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+
+/* Limits and other defines */
+/* The # proxy devices. Max minor # is one less than this */
+#define NUM_PX_DEVS (255)
+#define DEVNAME "proxy"
+#define DEBUGLEVEL (2)
+
+
+/* Data structure definitions */
+/* This structure describes the buffer and queues in one direction */
+struct cirbuf {
+ char *buf; /* points to sf circular buffer */
+ int widx; /* where to write next sf character */
+ int ridx; /* where to read next sf character */
+ int cidx; /* file closed at this index. ==-1 while open */
+ wait_queue_head_t que; /* sf readers wait on this queue */
+};
+
+/* This data structure describes one proxy device. There
+ * is one of these for each instance (minor #) of proxy.
+ * Since data flow is completely symmetric, we differentiate
+ * the two endpoints as East (e) and West (w), with the
+ * two corresponding directions ew and we.
+ */
+struct px {
+ int minor; /* minor number of this proxy instance */
+ struct cirbuf ewbuf;
+ struct cirbuf webuf;
+ struct semaphore sem; /* lock to protect nopen */
+ int nopen; /* number of opens on this device */
+ struct file *east; /* used to tell which cirbuf to use */
+ struct file *west; /* used to tell which cirbuf to use */
+ int eastaccmode; /* Access mode (O_RDONLY, O_WRONLY) */
+ int westaccmode; /* needed even after one side closes */
+};
+
+
+/* Function prototypes. */
+static int proxy_init_module(void);
+static void proxy_exit_module(void);
+static int proxy_open(struct inode *, struct file *);
+static int proxy_release(struct inode *, struct file *);
+static ssize_t proxy_read(struct file *, char *, size_t, loff_t *);
+static ssize_t proxy_write(struct file *, const char *, size_t, loff_t *);
+static unsigned int proxy_poll(struct file *, poll_table *);
+
+
+/* Global variables */
+static int buffersize = 0x1000; /* circular buffer is 0x1000 4K */
+static unsigned char numberofdevs = NUM_PX_DEVS;
+static int px_major; /* major device number */
+/* Debuglvl controls whether a printk is executed
+ * 0 = no printk at all
+ * 1 = printk on error only
+ * 2 = printk on errors and on init/remove
+ * 3 = debug prink to trace calls into proxy
+ * 4 = debug trace inside of proxy calls
+ */
+static unsigned char debuglevel = DEBUGLEVEL; /* printk verbosity */
+
+struct cdev px_cdev; /* a char device global */
+dev_t px_devicenumber; /* first device number */
+
+module_param(buffersize, int, S_IRUSR);
+module_param(debuglevel, byte, S_IRUSR);
+module_param(numberofdevs, byte, S_IRUSR);
+
+static struct px *px_devices; /* point to devices (minors) */
+
+/* map the callbacks into this driver */
+const struct file_operations proxy_fops = {
+ .owner = THIS_MODULE,
+ .open = proxy_open,
+ .read = proxy_read,
+ .write = proxy_write,
+ .poll = proxy_poll,
+ .release = proxy_release
+};
+
+
+/* Module description and macros */
+
+MODULE_DESCRIPTION
+("Transparently connects two user-space programs through a device");
+MODULE_AUTHOR("Bob Smith");
+MODULE_LICENSE("GPL");
+MODULE_PARM_DESC(buffersize, "Size of each buffer. default=4096 (4K) ");
+MODULE_PARM_DESC(debuglevel, "Debug level. Higher=verbose. default=2");
+MODULE_PARM_DESC(numberofdevs,
+ "Create this many minor devices. default=16");
+
+
+
+int proxy_init_module(void)
+{
+ 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);
+ return 0;
+ }
+ memset(px_devices, 0, numberofdevs * sizeof(struct px));
+
+ /* 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;
+ px_devices[i].ewbuf.cidx = -1;
+ px_devices[i].webuf.cidx = -1;
+ px_devices[i].east = (struct file *) 0; /* !=0 if open */
+ px_devices[i].west = (struct file *) 0;
+ init_waitqueue_head(&px_devices[i].ewbuf.que);
+ init_waitqueue_head(&px_devices[i].webuf.que);
+ px_devices[i].nopen = 0;
+#ifdef init_MUTEX
+ init_MUTEX(&px_devices[i].sem);
+#else
+ sema_init(&px_devices[i].sem, 1);
+#endif
+ }
+
+ /* alloc number of char devs in kernel */
+ err = alloc_chrdev_region(&px_devicenumber, 0, numberofdevs, DEVNAME);
+ if (err < 0) {
+ if (debuglevel >= 1)
+ pr_err("%s: init fails. err=%d.\n",
+ DEVNAME, err);
+ return err;
+ }
+ px_major = MAJOR(px_devicenumber); /* save assign major */
+ cdev_init(&px_cdev, &proxy_fops); /* init dev structures */
+ kobject_set_name(&(px_cdev.kobj), "proxy%d", px_devicenumber);
+
+ 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;
+ }
+
+ if (debuglevel >= 2)
+ pr_info("%s: Installed %d minor devices on major number %d.\n",
+ DEVNAME, numberofdevs, px_major);
+ return 0; /* success */
+}
+
+
+void proxy_exit_module(void)
+{
+ int i;
+ if (!px_devices)
+ return;
+
+ for (i = 0; i < numberofdevs; i++) {
+ kfree(px_devices[i].ewbuf.buf);
+ kfree(px_devices[i].webuf.buf);
+ }
+
+ cdev_del(&px_cdev); /* delete major device */
+ kfree(px_devices); /* free */
+ px_devices = NULL; /* reset pointer */
+ unregister_chrdev_region(px_devicenumber, numberofdevs);
+
+ if (debuglevel >= 2)
+ pr_info("%s: Uninstalled.\n", DEVNAME);
+}
+
+
+static int proxy_open(struct inode *inode, struct file *filp)
+{
+ int mnr = iminor(inode);
+ struct px *dev = &px_devices[mnr];
+
+ if (debuglevel >= 3)
+ pr_info("%s open. Minor#=%d.\n", DEVNAME, mnr);
+
+ if (down_interruptible(&dev->sem)) /* prevent races on open */
+ return -ERESTARTSYS;
+
+ if (dev->nopen >= 2) { /* Only two opens please! */
+ up(&dev->sem);
+ return -EBUSY;
+ }
+ dev->nopen = dev->nopen + 1;
+
+ 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);
+ 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);
+ up(&dev->sem);
+ return -ENOMEM;
+ }
+ }
+
+ /* store the proxy device in the file's private data */
+ filp->private_data = (void *) dev;
+ if (dev->east == (struct file *) 0) {
+ dev->east = filp; /* tells west from east */
+ dev->webuf.ridx = dev->webuf.widx; /* reader starts caught up */
+ dev->ewbuf.cidx = -1; /* xmit is open */
+ dev->webuf.cidx = -1; /* xmit is open */
+ if (dev->nopen == 2) { /* wake up other end */
+ wake_up_interruptible(&dev->webuf.que);
+ }
+ dev->eastaccmode = filp->f_flags;
+ } else if (dev->west == (struct file *) 0) {
+ dev->west = filp; /* tells east from west */
+ dev->ewbuf.ridx = dev->ewbuf.widx; /* reader starts caught up */
+ dev->webuf.cidx = -1;
+ dev->ewbuf.cidx = -1;
+ if (dev->nopen == 2) { /* wake up other end */
+ wake_up_interruptible(&dev->ewbuf.que);
+ }
+ dev->westaccmode = filp->f_flags;
+ } else if (debuglevel >= 1)
+ pr_err("%s: inconsistent open count.\n", DEVNAME);
+
+ up(&dev->sem); /* unlock sema we are done */
+
+ return nonseekable_open(inode, filp); /* success */
+}
+
+
+static int proxy_release(struct inode *inode, struct file *filp)
+{
+ struct px *dev = (struct px *) filp->private_data;
+
+ if (debuglevel >= 3)
+ 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 */
+ dev->ewbuf.cidx = dev->ewbuf.widx; /* set close index */
+ } else if (dev->west == filp) {
+ dev->west = (struct file *) 0; /* mark as not in use */
+ dev->webuf.cidx = dev->webuf.widx; /* set close index */
+ } else if (debuglevel >= 1)
+ pr_err("%s: inconsistent open count.\n", DEVNAME);
+
+ up(&dev->sem); /* unlock sema we are done */
+
+ return 0; /* success */
+}
+
+
+/* Utility to look for a full circular buffer */
+int is_full(struct cirbuf *pcbuffer)
+{
+ if ((pcbuffer->ridx - pcbuffer->widx == 1) ||
+ ((pcbuffer->ridx == 0) && (pcbuffer->widx == buffersize - 1)))
+ return 1;
+ else
+ return 0;
+}
+
+
+static ssize_t proxy_read(
+ struct file *filp, char __user *buff,
+ size_t count,
+ loff_t *offset)
+{
+ int ret;
+ int xfer; /* num bytes read from proxy buf */
+ int cpcnt; /* cp count and start location */
+ struct cirbuf *pcbuffer;
+
+ struct px *dev = (struct px *) filp->private_data;
+
+ if (debuglevel >= 3)
+ pr_info("%s: read %d char from dev%d, off=%lld.\n",
+ DEVNAME, count, dev->minor, *offset);
+
+ if (filp == dev->east)
+ pcbuffer = &dev->webuf;
+ else if (filp == dev->west)
+ pcbuffer = &dev->ewbuf;
+ else
+ return 0; /* should not get here */
+
+ /* cidx is set if writer is trying to close the file */
+ if (pcbuffer->ridx == pcbuffer->cidx)
+ return 0;
+
+ /* Wait here until new data is available */
+ while (pcbuffer->ridx == pcbuffer->widx) {
+ if (filp->f_flags & O_NONBLOCK)
+ return -EWOULDBLOCK;
+ /* wait on event queue, predicate is .. */
+ if (wait_event_interruptible(pcbuffer->que,
+ (pcbuffer->ridx != pcbuffer->widx))) {
+ if (debuglevel >= 1)
+ pr_err("%s: read failed in wait_event_interruptible\n",
+ DEVNAME);
+ return -ERESTARTSYS;
+ }
+ }
+
+ /* Copy the new data out to the user */
+ xfer = pcbuffer->widx - pcbuffer->ridx;
+ xfer = (xfer < 0) ? (xfer + buffersize) : xfer;
+ xfer = min_t(int, (int) count, xfer);
+ ret = xfer; /* we will handle these bytes */
+
+ cpcnt = buffersize - pcbuffer->ridx;
+ cpcnt = (cpcnt < xfer) ? cpcnt : xfer;
+ if (cpcnt) {
+ if (copy_to_user(buff, pcbuffer->buf + pcbuffer->ridx, cpcnt)) {
+ if (debuglevel >= 1)
+ pr_err("%s: read failed in copy_to_user.\n",
+ DEVNAME);
+ return -EFAULT;
+ }
+ }
+
+ if (xfer - cpcnt > 0) {
+ if (copy_to_user(buff + cpcnt, pcbuffer->buf, xfer - cpcnt)) {
+ if (debuglevel >= 1)
+ pr_err("%s: read failed in copy_to_user.\n",
+ DEVNAME);
+ return -EFAULT;
+ }
+ }
+ pcbuffer->ridx += xfer;
+ pcbuffer->ridx -= (pcbuffer->ridx > buffersize - 1) ? buffersize : 0;
+
+ /* This is what the writers have been waiting for */
+ wake_up_interruptible(&pcbuffer->que);
+
+ if (debuglevel >= 3)
+ pr_info("%s: read %d bytes.\n", DEVNAME, xfer);
+ return ret;
+}
+
+
+static ssize_t proxy_write(
+ struct file *filp,
+ const char __user *buff,
+ size_t count, loff_t *off)
+{
+ int ret;
+ int xfer; /* num bytes to read from user */
+ int cpcnt; /* num bytes in a single copy */
+ struct cirbuf *pcbuffer;
+
+ struct px *dev = (struct px *) filp->private_data;
+
+ if (debuglevel >= 3)
+ pr_info("%s: write %d char from dev%d\n",
+ DEVNAME, count, dev->minor);
+
+ if (filp == dev->east)
+ pcbuffer = &dev->ewbuf;
+ else if (filp == dev->west)
+ pcbuffer = &dev->webuf;
+ else {
+ if (debuglevel >= 3)
+ pr_err("%s: can't tell east from west.\n",
+ DEVNAME);
+ return 0; /* should not get here */
+ }
+
+ /* Wait here until new data is available to write */
+ while ((dev->nopen != 2) || is_full(pcbuffer)) {
+ if (filp->f_flags & O_NONBLOCK)
+ return -EWOULDBLOCK;
+ /* wait on event queue, predicate is .. */
+ if (wait_event_interruptible(pcbuffer->que,
+ ((dev->nopen == 2) && (!is_full(pcbuffer))))) {
+ if (debuglevel >= 1)
+ pr_err("%s: write failed in wait_event_interruptible.\n",
+ DEVNAME);
+ return -ERESTARTSYS;
+ }
+ }
+
+ xfer = pcbuffer->ridx - 1 - pcbuffer->widx;
+ xfer = (xfer < 0) ? xfer + buffersize : xfer;
+ xfer = min_t(int, (int) count, xfer);
+ ret = xfer;
+
+ cpcnt = min(xfer, buffersize - pcbuffer->widx);
+ if (cpcnt) {
+ if (copy_from_user(pcbuffer->buf + pcbuffer->widx,
+ buff, cpcnt)) {
+ if (debuglevel >= 1)
+ printk(
+ "%s: read failed in copy_from_user.\n",
+ DEVNAME);
+ return -EFAULT;
+ }
+ }
+
+ if (xfer - cpcnt > 0) {
+ if (copy_from_user(pcbuffer->buf, buff + cpcnt, xfer - cpcnt)) {
+ if (debuglevel >= 1)
+ printk(
+ "%s: read failed in copy_from_user.\n",
+ DEVNAME);
+ return -EFAULT;
+ }
+ }
+ pcbuffer->widx += xfer;
+ pcbuffer->widx -= (pcbuffer->widx > buffersize - 1) ? buffersize : 0;
+
+ /* Count=0 if writer is trying to close the file */
+ if (count == 0)
+ pcbuffer->cidx = pcbuffer->widx;
+
+ /* This is what the readers have been waiting for */
+ wake_up_interruptible(&pcbuffer->que);
+
+ if (debuglevel >= 3)
+ printk("%s: wrote %d bytes.\n", DEVNAME, ret);
+ return ret;
+}
+
+
+static unsigned int proxy_poll(struct file *filp, poll_table *ppt)
+{
+ int ready_mask = 0;
+ struct px *dev = filp->private_data;
+
+ poll_wait(filp, &dev->ewbuf.que, ppt);
+ poll_wait(filp, &dev->webuf.que, ppt);
+
+
+ if (filp == dev->west) {
+ /* Writable if there's space, the other end is connected,
+ * we haven't already written an end-of-file marker,
+ * the other side is not WRONLY, and our side is not O_RDONLY
+ */
+ if (!is_full(&dev->webuf) && (dev->nopen == 2)
+ && (dev->webuf.cidx != dev->webuf.widx)
+ && ((dev->eastaccmode & O_ACCMODE) != O_WRONLY)
+ && ((filp->f_flags & O_ACCMODE) != O_RDONLY)) {
+ ready_mask = POLLOUT | POLLWRNORM;
+ }
+ /* Readable if the buffer has data or we're at end of file,
+ * and the other sice is not RDONLY,
+ * and our side is not O_WRONLY
+ */
+ if (((dev->ewbuf.widx != dev->ewbuf.ridx)
+ || (dev->ewbuf.ridx == dev->ewbuf.cidx))
+ && ((dev->eastaccmode & O_ACCMODE) != O_RDONLY)
+ && ((filp->f_flags & O_ACCMODE) != O_WRONLY)) {
+ ready_mask |= (POLLIN | POLLRDNORM);
+ }
+ } else if (filp == dev->east) {
+ if (!is_full(&dev->ewbuf) && (dev->nopen == 2)
+ && (dev->ewbuf.cidx != dev->ewbuf.widx)
+ && ((dev->westaccmode & O_ACCMODE) != O_WRONLY)
+ && ((filp->f_flags & O_ACCMODE) != O_RDONLY)) {
+ ready_mask = POLLOUT | POLLWRNORM;
+ }
+ if (((dev->webuf.widx != dev->webuf.ridx)
+ || (dev->webuf.ridx == dev->webuf.cidx))
+ && ((dev->westaccmode & O_ACCMODE) != O_RDONLY)
+ && ((filp->f_flags & O_ACCMODE) != O_WRONLY)) {
+ ready_mask |= (POLLIN | POLLRDNORM);
+ }
+ }
+
+ if (debuglevel >= 3)
+ pr_info("%s: poll returns 0x%x.\n",
+ DEVNAME, ready_mask);
+ return ready_mask;
+}
+
+module_init(proxy_init_module);
+module_exit(proxy_exit_module);
--
1.7.10.4
^ permalink raw reply related [flat|nested] 36+ messages in thread
* Re: [PATCH 001/001] CHAR DRIVERS: a simple device to give daemons a /sys-like interface
2013-08-03 1:19 ` [PATCH 001/001] CHAR DRIVERS: a simple device to give daemons a /sys-like interface Bob Smith
@ 2013-08-03 1:56 ` Joe Perches
2013-08-03 2:35 ` Greg Kroah-Hartman
2013-08-03 22:38 ` Greg Kroah-Hartman
2 siblings, 0 replies; 36+ messages in thread
From: Joe Perches @ 2013-08-03 1:56 UTC (permalink / raw)
To: Bob Smith; +Cc: Arnd Bergmann, Greg Kroah-Hartman, linux-kernel
On Fri, 2013-08-02 at 18:19 -0700, Bob Smith wrote:
> 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:
> diff --git a/drivers/char/proxy.c b/drivers/char/proxy.c
[]
+int proxy_init_module(void)
> +{
> + 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.
> + return 0;
> + }
> + memset(px_devices, 0, numberofdevs * sizeof(struct px));
kcalloc instead of kmalloc/memset
> +
> + /* 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.
> + 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)
> + 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...
> +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);
> + 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.
> +static int proxy_release(struct inode *inode, struct file *filp)
> +{
> + struct px *dev = (struct px *) filp->private_data;
> +
> + if (debuglevel >= 3)
> + 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)
> + 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.
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 001/001] CHAR DRIVERS: a simple device to give daemons a /sys-like interface
2013-08-03 1:19 ` [PATCH 001/001] CHAR DRIVERS: a simple device to give daemons a /sys-like interface Bob Smith
2013-08-03 1:56 ` Joe Perches
@ 2013-08-03 2:35 ` Greg Kroah-Hartman
2013-08-03 18:12 ` Bob Smith
2013-08-03 22:38 ` Greg Kroah-Hartman
2 siblings, 1 reply; 36+ messages in thread
From: Greg Kroah-Hartman @ 2013-08-03 2:35 UTC (permalink / raw)
To: Bob Smith; +Cc: Arnd Bergmann, linux-kernel
On Fri, Aug 02, 2013 at 06:19:19PM -0700, Bob Smith wrote:
> 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
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 001/001] CHAR DRIVERS: a simple device to give daemons a /sys-like interface
2013-08-03 2:35 ` Greg Kroah-Hartman
@ 2013-08-03 18:12 ` Bob Smith
0 siblings, 0 replies; 36+ messages in thread
From: Bob Smith @ 2013-08-03 18:12 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: Arnd Bergmann, linux-kernel
Greg
Thanks for your reply. I'll reply to your comments in reverse order.
Greg Kroah-Hartman wrote:
> 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
Greg Kroah-Hartman wrote:
> 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
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 001/001] CHAR DRIVERS: a simple device to give daemons a /sys-like interface
2013-08-03 1:19 ` [PATCH 001/001] CHAR DRIVERS: a simple device to give daemons a /sys-like interface Bob Smith
2013-08-03 1:56 ` Joe Perches
2013-08-03 2:35 ` Greg Kroah-Hartman
@ 2013-08-03 22:38 ` Greg Kroah-Hartman
2013-08-04 21:54 ` Bob Smith
2 siblings, 1 reply; 36+ messages in thread
From: Greg Kroah-Hartman @ 2013-08-03 22:38 UTC (permalink / raw)
To: Bob Smith; +Cc: Arnd Bergmann, linux-kernel
On Fri, Aug 02, 2013 at 06:19:19PM -0700, Bob Smith wrote:
> 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:
> From 7ee4391af95b828179cf5627f8b431c3301c5057 Mon Sep 17 00:00:00 2001
> From: Bob Smith <bsmith@linuxtoys.org>
> 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.
> ---
> 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
>
> diff --git a/Documentation/proxy.txt b/Documentation/proxy.txt
> new file mode 100644
> index 0000000..6b9206a
> --- /dev/null
> +++ b/Documentation/proxy.txt
> @@ -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.
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?
> +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.
> +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
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 001/001] CHAR DRIVERS: a simple device to give daemons a /sys-like interface
2013-08-03 22:38 ` Greg Kroah-Hartman
@ 2013-08-04 21:54 ` Bob Smith
2013-08-04 23:19 ` Greg Kroah-Hartman
0 siblings, 1 reply; 36+ messages in thread
From: Bob Smith @ 2013-08-04 21:54 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: Arnd Bergmann, linux-kernel
Greg
I've added some white space and snipped some text to make
the questions more visible.
Greg Kroah-Hartman wrote:
> 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.
>> +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.
>> +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.
>> +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.
> 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
> 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
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 001/001] CHAR DRIVERS: a simple device to give daemons a /sys-like interface
2013-08-04 21:54 ` Bob Smith
@ 2013-08-04 23:19 ` Greg Kroah-Hartman
2013-08-05 23:46 ` Bob Smith
0 siblings, 1 reply; 36+ messages in thread
From: Greg Kroah-Hartman @ 2013-08-04 23:19 UTC (permalink / raw)
To: Bob Smith; +Cc: Arnd Bergmann, linux-kernel
On Sun, Aug 04, 2013 at 02:54:46PM -0700, Bob Smith wrote:
> >>+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.
> 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.
> >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.
> > 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.
> 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.
> 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
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 001/001] CHAR DRIVERS: a simple device to give daemons a /sys-like interface
2013-08-04 23:19 ` Greg Kroah-Hartman
@ 2013-08-05 23:46 ` Bob Smith
2013-08-06 9:46 ` Greg Kroah-Hartman
0 siblings, 1 reply; 36+ messages in thread
From: Bob Smith @ 2013-08-05 23:46 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: Arnd Bergmann, linux-kernel
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
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 001/001] CHAR DRIVERS: a simple device to give daemons a /sys-like interface
2013-08-05 23:46 ` Bob Smith
@ 2013-08-06 9:46 ` Greg Kroah-Hartman
2013-08-07 19:02 ` Bob Smith
2013-08-07 21:38 ` Bob Smith
0 siblings, 2 replies; 36+ messages in thread
From: Greg Kroah-Hartman @ 2013-08-06 9:46 UTC (permalink / raw)
To: Bob Smith; +Cc: Arnd Bergmann, linux-kernel
On Mon, Aug 05, 2013 at 04:46:32PM -0700, Bob Smith wrote:
> 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
No it shouldn't, that is userspace talking to the kernel, you aren't
doing that at all.
> 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?
> 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.
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.
> 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...
> 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?
> 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!
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.
> 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
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 001/001] CHAR DRIVERS: a simple device to give daemons a /sys-like interface
2013-08-06 9:46 ` Greg Kroah-Hartman
@ 2013-08-07 19:02 ` Bob Smith
2013-08-07 19:27 ` Greg Kroah-Hartman
2013-08-07 21:38 ` Bob Smith
1 sibling, 1 reply; 36+ messages in thread
From: Bob Smith @ 2013-08-07 19:02 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: Arnd Bergmann, linux-kernel
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);
}
}
}
}
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 001/001] CHAR DRIVERS: a simple device to give daemons a /sys-like interface
2013-08-07 19:02 ` Bob Smith
@ 2013-08-07 19:27 ` Greg Kroah-Hartman
2013-08-07 19:39 ` Bob Smith
0 siblings, 1 reply; 36+ messages in thread
From: Greg Kroah-Hartman @ 2013-08-07 19:27 UTC (permalink / raw)
To: Bob Smith; +Cc: Arnd Bergmann, linux-kernel
On Wed, Aug 07, 2013 at 12:02:03PM -0700, Bob Smith wrote:
> 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
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...
> * sudo chmod 666 /dev/proxyout /dev/proxyctrl
That's mighty permissive :(
> * 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
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 001/001] CHAR DRIVERS: a simple device to give daemons a /sys-like interface
2013-08-07 19:27 ` Greg Kroah-Hartman
@ 2013-08-07 19:39 ` Bob Smith
2013-08-07 19:51 ` Greg Kroah-Hartman
2013-08-07 19:54 ` Greg Kroah-Hartman
0 siblings, 2 replies; 36+ messages in thread
From: Bob Smith @ 2013-08-07 19:39 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: Arnd Bergmann, linux-kernel
Greg Kroah-Hartman wrote:
>> * 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.
>> * 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?
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
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 001/001] CHAR DRIVERS: a simple device to give daemons a /sys-like interface
2013-08-07 19:39 ` Bob Smith
@ 2013-08-07 19:51 ` Greg Kroah-Hartman
2013-08-07 19:54 ` Greg Kroah-Hartman
1 sibling, 0 replies; 36+ messages in thread
From: Greg Kroah-Hartman @ 2013-08-07 19:51 UTC (permalink / raw)
To: Bob Smith; +Cc: Arnd Bergmann, linux-kernel
On Wed, Aug 07, 2013 at 12:39:48PM -0700, Bob Smith wrote:
> Greg Kroah-Hartman wrote:
> >> * 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
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 001/001] CHAR DRIVERS: a simple device to give daemons a /sys-like interface
2013-08-07 19:39 ` Bob Smith
2013-08-07 19:51 ` Greg Kroah-Hartman
@ 2013-08-07 19:54 ` Greg Kroah-Hartman
2013-08-07 21:04 ` Bob Smith
2013-08-07 21:28 ` Bob Smith
1 sibling, 2 replies; 36+ messages in thread
From: Greg Kroah-Hartman @ 2013-08-07 19:54 UTC (permalink / raw)
To: Bob Smith; +Cc: Arnd Bergmann, linux-kernel
On Wed, Aug 07, 2013 at 12:39:48PM -0700, Bob Smith wrote:
> Greg Kroah-Hartman wrote:
> >> * 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.
>
>
> >> * 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?
>
> 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.
> 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
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 001/001] CHAR DRIVERS: a simple device to give daemons a /sys-like interface
2013-08-07 19:54 ` Greg Kroah-Hartman
@ 2013-08-07 21:04 ` Bob Smith
2013-08-07 21:33 ` Greg Kroah-Hartman
2013-08-07 21:28 ` Bob Smith
1 sibling, 1 reply; 36+ messages in thread
From: Bob Smith @ 2013-08-07 21:04 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: Arnd Bergmann, linux-kernel
Greg Kroah-Hartman wrote:
>> 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.
>
> 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.
>
> 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
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 001/001] CHAR DRIVERS: a simple device to give daemons a /sys-like interface
2013-08-07 19:54 ` Greg Kroah-Hartman
2013-08-07 21:04 ` Bob Smith
@ 2013-08-07 21:28 ` Bob Smith
2013-08-07 21:40 ` Greg Kroah-Hartman
1 sibling, 1 reply; 36+ messages in thread
From: Bob Smith @ 2013-08-07 21:28 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: Arnd Bergmann, linux-kernel
Greg Kroah-Hartman wrote:
> 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.
> 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
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 001/001] CHAR DRIVERS: a simple device to give daemons a /sys-like interface
2013-08-07 21:04 ` Bob Smith
@ 2013-08-07 21:33 ` Greg Kroah-Hartman
2013-08-08 21:23 ` Bob Smith
2013-08-09 22:14 ` Bob Smith
0 siblings, 2 replies; 36+ messages in thread
From: Greg Kroah-Hartman @ 2013-08-07 21:33 UTC (permalink / raw)
To: Bob Smith; +Cc: Arnd Bergmann, linux-kernel
On Wed, Aug 07, 2013 at 02:04:52PM -0700, Bob Smith wrote:
> Greg Kroah-Hartman wrote:
> >> 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.
You are mixing protocols and bindings and system calls up it seems.
They are not the same at all.
> >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.
> 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
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 001/001] CHAR DRIVERS: a simple device to give daemons a /sys-like interface
2013-08-06 9:46 ` Greg Kroah-Hartman
2013-08-07 19:02 ` Bob Smith
@ 2013-08-07 21:38 ` Bob Smith
1 sibling, 0 replies; 36+ messages in thread
From: Bob Smith @ 2013-08-07 21:38 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: Arnd Bergmann, linux-kernel
Greg Kroah-Hartman wrote:
>> 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
>
>> 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
>
> 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.
>
>> 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.
>
>> 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.
>
> 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
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 001/001] CHAR DRIVERS: a simple device to give daemons a /sys-like interface
2013-08-07 21:28 ` Bob Smith
@ 2013-08-07 21:40 ` Greg Kroah-Hartman
2013-08-07 21:53 ` Bob Smith
0 siblings, 1 reply; 36+ messages in thread
From: Greg Kroah-Hartman @ 2013-08-07 21:40 UTC (permalink / raw)
To: Bob Smith; +Cc: Arnd Bergmann, linux-kernel
On Wed, Aug 07, 2013 at 02:28:49PM -0700, Bob Smith wrote:
> Greg Kroah-Hartman wrote:
> > 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.
> 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.
> > 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
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 001/001] CHAR DRIVERS: a simple device to give daemons a /sys-like interface
2013-08-07 21:40 ` Greg Kroah-Hartman
@ 2013-08-07 21:53 ` Bob Smith
2013-08-09 21:54 ` Greg Kroah-Hartman
0 siblings, 1 reply; 36+ messages in thread
From: Bob Smith @ 2013-08-07 21:53 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: Arnd Bergmann, linux-kernel
Greg Kroah-Hartman wrote:
>> 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.
>
>> 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.
>
>>> 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
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 001/001] CHAR DRIVERS: a simple device to give daemons a /sys-like interface
2013-08-07 21:33 ` Greg Kroah-Hartman
@ 2013-08-08 21:23 ` Bob Smith
2013-08-09 21:52 ` Greg Kroah-Hartman
2013-08-09 22:14 ` Bob Smith
1 sibling, 1 reply; 36+ messages in thread
From: Bob Smith @ 2013-08-08 21:23 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: Arnd Bergmann, linux-kernel
Greg Kroah-Hartman wrote:>
> 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
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 001/001] CHAR DRIVERS: a simple device to give daemons a /sys-like interface
2013-08-08 21:23 ` Bob Smith
@ 2013-08-09 21:52 ` Greg Kroah-Hartman
2013-08-09 22:20 ` Bob Smith
0 siblings, 1 reply; 36+ messages in thread
From: Greg Kroah-Hartman @ 2013-08-09 21:52 UTC (permalink / raw)
To: Bob Smith; +Cc: Arnd Bergmann, linux-kernel
On Thu, Aug 08, 2013 at 02:23:06PM -0700, Bob Smith wrote:
> Greg Kroah-Hartman wrote:>
> > 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.
I fail to understand how you will use this code to write a "userspace
device driver" at all.
still confused,
greg k-h
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 001/001] CHAR DRIVERS: a simple device to give daemons a /sys-like interface
2013-08-07 21:53 ` Bob Smith
@ 2013-08-09 21:54 ` Greg Kroah-Hartman
2013-08-09 22:51 ` Bob Smith
0 siblings, 1 reply; 36+ messages in thread
From: Greg Kroah-Hartman @ 2013-08-09 21:54 UTC (permalink / raw)
To: Bob Smith; +Cc: Arnd Bergmann, linux-kernel
On Wed, Aug 07, 2013 at 02:53:50PM -0700, Bob Smith wrote:
> Greg Kroah-Hartman wrote:
> >>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.
> 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...
> >>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.
>
> >
> >>> 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?
Yes it is, modern userspace does not create any device nodes anymore,
please let's not regress on that point.
thanks,
greg k-h
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 001/001] CHAR DRIVERS: a simple device to give daemons a /sys-like interface
2013-08-07 21:33 ` Greg Kroah-Hartman
2013-08-08 21:23 ` Bob Smith
@ 2013-08-09 22:14 ` Bob Smith
2013-08-09 23:01 ` Greg Kroah-Hartman
1 sibling, 1 reply; 36+ messages in thread
From: Bob Smith @ 2013-08-09 22:14 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: Arnd Bergmann, linux-kernel
Greg Kroah-Hartman wrote:
(snip)
> 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
>
> (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!" :)
>
> (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.
>
> 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.
>
> greg k-h
Greg, sorry this message was so long, and thanks again for your patience.
Bob Smith
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 001/001] CHAR DRIVERS: a simple device to give daemons a /sys-like interface
2013-08-09 21:52 ` Greg Kroah-Hartman
@ 2013-08-09 22:20 ` Bob Smith
0 siblings, 0 replies; 36+ messages in thread
From: Bob Smith @ 2013-08-09 22:20 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: Arnd Bergmann, linux-kernel
Greg Kroah-Hartman wrote:
> On Thu, Aug 08, 2013 at 02:23:06PM -0700, Bob Smith wrote:
>> 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
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 001/001] CHAR DRIVERS: a simple device to give daemons a /sys-like interface
2013-08-09 21:54 ` Greg Kroah-Hartman
@ 2013-08-09 22:51 ` Bob Smith
2013-08-09 23:04 ` Greg Kroah-Hartman
0 siblings, 1 reply; 36+ messages in thread
From: Bob Smith @ 2013-08-09 22:51 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: Arnd Bergmann, linux-kernel
Greg Kroah-Hartman wrote:
> On Wed, Aug 07, 2013 at 02:53:50PM -0700, Bob Smith wrote:
>> 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.
>
>> 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.
>
> 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.
>
> (snip)
>> 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
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 001/001] CHAR DRIVERS: a simple device to give daemons a /sys-like interface
2013-08-09 22:14 ` Bob Smith
@ 2013-08-09 23:01 ` Greg Kroah-Hartman
2013-08-09 23:35 ` Bob Smith
2013-08-10 20:08 ` Bob Smith
0 siblings, 2 replies; 36+ messages in thread
From: Greg Kroah-Hartman @ 2013-08-09 23:01 UTC (permalink / raw)
To: Bob Smith; +Cc: Arnd Bergmann, linux-kernel
On Fri, Aug 09, 2013 at 03:14:10PM -0700, Bob Smith wrote:
> Greg Kroah-Hartman wrote:
> (snip)
> > 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.
> - 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.
> - 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.
> > (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.
> 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!" :)
Not really, you are just using an IPC to talk to a "real" device driver.
> 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
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 001/001] CHAR DRIVERS: a simple device to give daemons a /sys-like interface
2013-08-09 22:51 ` Bob Smith
@ 2013-08-09 23:04 ` Greg Kroah-Hartman
0 siblings, 0 replies; 36+ messages in thread
From: Greg Kroah-Hartman @ 2013-08-09 23:04 UTC (permalink / raw)
To: Bob Smith; +Cc: Arnd Bergmann, linux-kernel
On Fri, Aug 09, 2013 at 03:51:39PM -0700, Bob Smith wrote:
> Greg Kroah-Hartman wrote:
> >On Wed, Aug 07, 2013 at 02:53:50PM -0700, Bob Smith wrote:
> >>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.
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.
> >>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.
> >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?
> > (snip)
> >>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
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 001/001] CHAR DRIVERS: a simple device to give daemons a /sys-like interface
2013-08-09 23:01 ` Greg Kroah-Hartman
@ 2013-08-09 23:35 ` Bob Smith
2013-08-09 23:46 ` Greg Kroah-Hartman
2013-08-10 20:08 ` Bob Smith
1 sibling, 1 reply; 36+ messages in thread
From: Bob Smith @ 2013-08-09 23:35 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: Arnd Bergmann, linux-kernel
Greg Kroah-Hartman wrote:
> 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.
>
>> - 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.
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.
>
>> 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.
>
>> 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)
>
> 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.
>
> 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.
>
> 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.
Greg Kroah-Hartman wrote:
> 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
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 001/001] CHAR DRIVERS: a simple device to give daemons a /sys-like interface
2013-08-09 23:35 ` Bob Smith
@ 2013-08-09 23:46 ` Greg Kroah-Hartman
0 siblings, 0 replies; 36+ messages in thread
From: Greg Kroah-Hartman @ 2013-08-09 23:46 UTC (permalink / raw)
To: Bob Smith; +Cc: Arnd Bergmann, linux-kernel
On Fri, Aug 09, 2013 at 04:35:16PM -0700, Bob Smith wrote:
> Greg Kroah-Hartman wrote:
> >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 :)
> >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.
> >>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)
> >
> >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 "===".
> >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
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 001/001] CHAR DRIVERS: a simple device to give daemons a /sys-like interface
2013-08-09 23:01 ` Greg Kroah-Hartman
2013-08-09 23:35 ` Bob Smith
@ 2013-08-10 20:08 ` Bob Smith
2013-08-10 20:29 ` richard -rw- weinberger
2013-08-10 21:43 ` Arnd Bergmann
1 sibling, 2 replies; 36+ messages in thread
From: Bob Smith @ 2013-08-10 20:08 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: Arnd Bergmann, linux-kernel
Greg Kroah-Hartman wrote:
> 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
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 001/001] CHAR DRIVERS: a simple device to give daemons a /sys-like interface
2013-08-10 20:08 ` Bob Smith
@ 2013-08-10 20:29 ` richard -rw- weinberger
2013-08-10 20:49 ` Bob Smith
2013-08-10 21:43 ` Arnd Bergmann
1 sibling, 1 reply; 36+ messages in thread
From: richard -rw- weinberger @ 2013-08-10 20:29 UTC (permalink / raw)
To: Bob Smith; +Cc: Greg Kroah-Hartman, Arnd Bergmann, LKML
On Sat, Aug 10, 2013 at 10:08 PM, Bob Smith <bsmith@linuxtoys.org> wrote:
> Greg Kroah-Hartman wrote:
>>
>> 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.
/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.
> bye
> Bob Smith
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
--
Thanks,
//richard
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 001/001] CHAR DRIVERS: a simple device to give daemons a /sys-like interface
2013-08-10 20:29 ` richard -rw- weinberger
@ 2013-08-10 20:49 ` Bob Smith
0 siblings, 0 replies; 36+ messages in thread
From: Bob Smith @ 2013-08-10 20:49 UTC (permalink / raw)
To: richard -rw- weinberger; +Cc: Greg Kroah-Hartman, Arnd Bergmann, LKML
richard -rw- weinberger wrote:
>> 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.
> /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.
> 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
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 001/001] CHAR DRIVERS: a simple device to give daemons a /sys-like interface
2013-08-10 20:08 ` Bob Smith
2013-08-10 20:29 ` richard -rw- weinberger
@ 2013-08-10 21:43 ` Arnd Bergmann
2013-08-10 22:07 ` Bob Smith
1 sibling, 1 reply; 36+ messages in thread
From: Arnd Bergmann @ 2013-08-10 21:43 UTC (permalink / raw)
To: Bob Smith; +Cc: Greg Kroah-Hartman, linux-kernel
On Saturday 10 August 2013, Bob Smith wrote:
> 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
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 001/001] CHAR DRIVERS: a simple device to give daemons a /sys-like interface
2013-08-10 21:43 ` Arnd Bergmann
@ 2013-08-10 22:07 ` Bob Smith
2013-08-13 20:15 ` Arnd Bergmann
0 siblings, 1 reply; 36+ messages in thread
From: Bob Smith @ 2013-08-10 22:07 UTC (permalink / raw)
To: Arnd Bergmann; +Cc: Greg Kroah-Hartman, linux-kernel
Arnd Bergmann wrote:
>> 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
> 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
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 001/001] CHAR DRIVERS: a simple device to give daemons a /sys-like interface
2013-08-10 22:07 ` Bob Smith
@ 2013-08-13 20:15 ` Arnd Bergmann
0 siblings, 0 replies; 36+ messages in thread
From: Arnd Bergmann @ 2013-08-13 20:15 UTC (permalink / raw)
To: Bob Smith; +Cc: Greg Kroah-Hartman, linux-kernel
On Sunday 11 August 2013, Bob Smith wrote:
> Arnd Bergmann wrote:
> >> 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
>
> > 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.
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
^ permalink raw reply [flat|nested] 36+ messages in thread
end of thread, other threads:[~2013-08-13 20:15 UTC | newest]
Thread overview: 36+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <51FC5478.40500@linuxtoys.org>
2013-08-03 1:19 ` [PATCH 001/001] CHAR DRIVERS: a simple device to give daemons a /sys-like interface Bob Smith
2013-08-03 1:56 ` Joe Perches
2013-08-03 2:35 ` Greg Kroah-Hartman
2013-08-03 18:12 ` Bob Smith
2013-08-03 22:38 ` Greg Kroah-Hartman
2013-08-04 21:54 ` Bob Smith
2013-08-04 23:19 ` Greg Kroah-Hartman
2013-08-05 23:46 ` Bob Smith
2013-08-06 9:46 ` Greg Kroah-Hartman
2013-08-07 19:02 ` Bob Smith
2013-08-07 19:27 ` Greg Kroah-Hartman
2013-08-07 19:39 ` Bob Smith
2013-08-07 19:51 ` Greg Kroah-Hartman
2013-08-07 19:54 ` Greg Kroah-Hartman
2013-08-07 21:04 ` Bob Smith
2013-08-07 21:33 ` Greg Kroah-Hartman
2013-08-08 21:23 ` Bob Smith
2013-08-09 21:52 ` Greg Kroah-Hartman
2013-08-09 22:20 ` Bob Smith
2013-08-09 22:14 ` Bob Smith
2013-08-09 23:01 ` Greg Kroah-Hartman
2013-08-09 23:35 ` Bob Smith
2013-08-09 23:46 ` Greg Kroah-Hartman
2013-08-10 20:08 ` Bob Smith
2013-08-10 20:29 ` richard -rw- weinberger
2013-08-10 20:49 ` Bob Smith
2013-08-10 21:43 ` Arnd Bergmann
2013-08-10 22:07 ` Bob Smith
2013-08-13 20:15 ` Arnd Bergmann
2013-08-07 21:28 ` Bob Smith
2013-08-07 21:40 ` Greg Kroah-Hartman
2013-08-07 21:53 ` Bob Smith
2013-08-09 21:54 ` Greg Kroah-Hartman
2013-08-09 22:51 ` Bob Smith
2013-08-09 23:04 ` Greg Kroah-Hartman
2013-08-07 21:38 ` Bob Smith
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox