有时需要在驱动中,执行shell脚本,这时可通过用户层来实现。具体的实现为
相应的Makefile如下
uevent.c
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/kfifo.h>
#include <linux/wait.h>
#include <linux/poll.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/miscdevice.h>
#define DEVICE_NAME "uevent"
#define FIFO_SIZE 1024
static DEFINE_MUTEX(read_lock);
static struct miscdevice uevent_dev;
static wait_queue_head_t uevent_wait;
typedef STRUCT_KFIFO_REC_1(FIFO_SIZE) uevent_fifo;
static uevent_fifo uevent;
void uevent_shell(char *cmd)
{
char buf[100];
printk("the uevent shell is %s\n",cmd);
kfifo_in(&uevent,cmd,strlen(cmd)+1);
//kfifo_out(&uevent,buf,sizeof(buf));
//printk("the kfifio out is %s",buf);
wake_up_interruptible(&uevent_wait);
}
EXPORT_SYMBOL(uevent_shell);
int uevent_open(struct inode *node, struct file *filp)
{
return 0;
}
static unsigned int uevent_poll(struct file *file,struct poll_table_struct *poll)
{
unsigned int mask=0;
poll_wait(file,&uevent_wait,poll);
if(!kfifo_is_empty(&uevent))
mask |= POLLIN | POLLRDNORM;
return mask;
}
static ssize_t uevent_read(struct file *file, char __user *buf,size_t count, loff_t *ppos)
{
int ret;
unsigned int copied;
if (mutex_lock_interruptible(&read_lock))
return -ERESTARTSYS;
ret = kfifo_to_user(&uevent, buf, count, &copied);
mutex_unlock(&read_lock);
return ret ? ret : copied;
}
int uevent_release(struct inode *node, struct file *filp)
{
return 0;
}
static struct file_operations uevent_dev_fops={
.owner = THIS_MODULE,
.open = uevent_open,
.poll = uevent_poll,
.read = uevent_read,
.release = uevent_release,
};
static struct miscdevice uevent_dev = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &uevent_dev_fops,
};
static int __init uevent_init(void)
{
int ret;
char *cmd="ls -al";
char *cmd2="du";
char *cmd3="mount";
printk("%s\n",__func__);
ret = misc_register(&uevent_dev);
init_waitqueue_head(&uevent_wait);
INIT_KFIFO(uevent);
msleep(1000);
msleep(1000);
msleep(1000);
uevent_shell(cmd);
msleep(1000);
msleep(1000);
uevent_shell(cmd2);
msleep(1000);
msleep(1000);
msleep(1000);
uevent_shell(cmd3);
return ret;
}
static void __exit uevent_exit(void)
{
misc_deregister(&uevent_dev);
printk("%s\n",__func__);
}
module_init(uevent_init);
module_exit(uevent_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("www");
用户层的app如下
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/select.h>
#include <unistd.h>
#include <signal.h>
#include <poll.h>
#define dev_name "uevent"
void systemstatus(int status)
{
if (-1 == status)
{
printf("system error!");
}
else
{
printf("exit status value = [0x%x]\n", status);
if (WIFEXITED(status))
{
if (WEXITSTATUS(status) == 0)
{
printf("run shell script successfully.\n");
}
else
{
printf("run shell script fail, script exit code: %d\n", WEXITSTATUS(status));
}
}
else
{
printf("exit status = [%d]\n", WEXITSTATUS(status));
}
}
}
int main(void)
{
struct pollfd fds;
int fd,ret,status;;
char dev_point[20];
unsigned char buf[100];
snprintf(dev_point,sizeof(buf),"/dev/%s",dev_name);
fd = open(dev_point, O_RDWR);
if(fd < 0)
{
perror("open");
return -1;
}
fds.fd=fd;
fds.events=POLLIN;
while(1)
{
poll(&fds,1,-1);
ret=read(fd,&buf,sizeof(buf));
status=system(buf);
systemstatus(status);
}
close(fd);
return 0;
}
相应的Makefile如下
ifeq ($(KERNELRELEASE),)
KERNELDIR ?= /usr/src/linux-headers-4.4.0-31-generic/
PWD :=$(shell pwd)
EXTRA_LIBS += -lpthread -static
CC=gcc
EXEC = app
OBJS = app.o
all: $(EXEC) modules
$(EXEC): $(OBJS)
$(CC) $(LDFLAGS) -o $@ $(OBJS) $(EXTRA_LIBS)
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
modules_install:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install
clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions modules.order Module.symvers
.PHONY: modules modules_install clean
else
obj-m:= uevent.o
endif