how to run user program from a kernel device driver
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
how to run user program from a kernel device driver
Hi.
I have a ARM dev board. It provides several buttons and sample driver codes. When i press one button, it call "printk" to print messages like "xx button is pressed" on the console.
The question is how can i notice my program running in the user mode? can i send a signal in the button driver to user processes? or can i start a user mode process intead of print a message on the console?
As all known, many C lib funcs and linux sys calls not available in kernel mode, such as, we must use printk rather than printf which is in C lib. What can I do to finish my job ?
Thanks.
Click here to see the post LQ members have rated as the most helpful post in this thread.
You need an input driver for your device. If your device is not too rare, it most probably has such a driver written for it already; otherwise you can create or modify an existing one that is close enough to your device. You (the programmer) can choose which event or events (keyboard key, mouse button, or other human interface thingy) the buttons produce, quite freely. This way all existing applications will support the buttons (assuming you pick input events the applications recognize). You can also choose rare or custom events, so that applications will ignore the event, but your own applications can detect it very easily, using the normal input event system.
There are other routes you could take, but the above is the easiest, and will yield the best results in most situations. After all, the buttons are an input device, right?
#define GPIO_BTN 38
static irqreturn_t gpio_btn_handler(int irq, void *dev_id);
static void __init gpio_btn(void)
{
int error; int irq;
orion_gpio_set_valid(GPIO_BTN, GPIO_INPUT_OK);
error = gpio_request(GPIO_BTN, "gpio_btn");
if ( error<0 ) { pr_err("gpio_btn: failed to request GPIO %d, error %d \n",GPIO_BTN, error); }
error = gpio_direction_input(GPIO_BTN);
if ( error<0 )
{ pr_err("gpio_btn: failed to configure input for GPIO %d, error %d \n",GPIO_BTN, error); }
irq = gpio_to_irq(GPIO_BTN);
if ( irq < 0)
{ pr_err("gpio_btn: Unable to get irq number for GPIO %d, error %d \n",GPIO_BTN, irq); }
error = request_irq(irq, gpio_btn_handler, IRQF_TRIGGER_RISING, "gpio_btn", NULL);
if ( error )
{ pr_err("gpio_btn: failed to request_irq for GPIO/irq %d %d, error %d \n",GPIO_BTN,irq, error); }
printk("gpio_btn is called sucessfully! \n");
}
// we want to start our own program here.
// it seems that we cannot use system() function to start a new process in kernel mode.
// many C functions like printf are not available in kernel mode
// any other way to solve the problem ???
static irqreturn_t gpio_btn_handler(int irq, void *dev_id)
{
printk(" the gpio is triggered, the irq is %d !\n",irq);
return 1;
}
void __exit gpio_exit(void)
{
//we can leave it empty;
}
module_init(gpio_btn);
module_exit(gpio_exit);
//first copy this file into kernel souce tree "drivers/char"; then add the statements "obj-y +=gpio_btn.o" into the file "drivers/char/Makefile"
//after building the kernel, the source code can be built into the kernel.
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/irqreturn.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#define GPIO_BTN 38
static irqreturn_t gpio_btn_handler(int irq, void *dev_id);
static void __init gpio_btn(void)
{
int error; int irq;
orion_gpio_set_valid(GPIO_BTN, GPIO_INPUT_OK);
error = gpio_request(GPIO_BTN, "gpio_btn");
if ( error<0 ) { pr_err("gpio_btn: failed to request GPIO %d, error %d \n",GPIO_BTN, error); }
error = gpio_direction_input(GPIO_BTN);
if ( error<0 )
{ pr_err("gpio_btn: failed to configure input for GPIO %d, error %d \n",GPIO_BTN, error); }
irq = gpio_to_irq(GPIO_BTN);
if ( irq < 0)
{ pr_err("gpio_btn: Unable to get irq number for GPIO %d, error %d \n",GPIO_BTN, irq); }
error = request_irq(irq, gpio_btn_handler, IRQF_TRIGGER_RISING, "gpio_btn", NULL);
if ( error )
{ pr_err("gpio_btn: failed to request_irq for GPIO/irq %d %d, error %d \n",GPIO_BTN,irq, error); }
printk("gpio_btn is called sucessfully! \n");
}
// we want to start our own program here.
// it seems that we cannot use system() function to start a new process in kernel mode.
// many C functions like printf are not available in kernel mode
// any other way to solve the problem ???
static irqreturn_t gpio_btn_handler(int irq, void *dev_id)
{
printk(" the gpio is triggered, the irq is %d !\n",irq);
return 1;
}
void __exit gpio_exit(void)
{
//we can leave it empty;
}
module_init(gpio_btn);
module_exit(gpio_exit);
//first copy this file into kernel souce tree "drivers/char"; then add the statements "obj-y +=gpio_btn.o" into the file "drivers/char/Makefile"
//after building the kernel, the source code can be built into the kernel.
The comments state that you want the kernel to run a userspace application whenever the button is pressed.
Normally this is solved the other way around. You have a small userspace daemon, which listens to the kernel, and when a button event occurs, the userspace daemon starts the application. You can communicate via the input system, a procfs (/proc/) or sysfs (/sys/) file, or via a character device. A character device is likely the best option here.
If you use a character device, then you can use a blocking read in the userspace daemon. Basically, there will be no data coming from the device, until the button is pressed (or released). I recommend you use a fixed-size record, with the value completely describing the button event -- this lets you expand the functionality later if needed. Having the event record be e.g. 8 bytes is probably a good idea. This way, the daemon will block at reading from the input device, not consuming any CPU time, unless something interesting happens. Such a daemon can be written to be very, very small, so it'll consume very little RAM too.
Depending on the userspace application, you might wish to merge it with the daemon, so that it is always present, just not consuming CPU time unless a button is pressed.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.