在驱动中执行shell脚本的一种方法

本文介绍了一种在Linux驱动程序中执行Shell脚本的方法,通过用户层与内核层的交互实现。具体实现了uevent_shell函数用于发送命令,并通过文件操作接口进行读取。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

有时需要在驱动中,执行shell脚本,这时可通过用户层来实现。具体的实现为

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



### 关于 Navicat Premium 16 定时导出导入的配置教程 Navicat Premium 16 提供了一种便捷的方式来实现数据库的定时导出导入操作。通过其内置的任务调度功能,可以轻松安排定期执行的数据传输、备份或其他自动化任务[^3]。 #### 配置定时导出/导入的方法 1. **打开“计划”窗口** 启动 Navicat Premium 16 并连接到目标数据库后,在顶部菜单栏中选择 `工具` -> `计划`,或者右键单击某个已建立的连接并选择 `新建计划`[^4]。 2. **创建新计划** 在弹出的对话框中点击 `新建` 按钮来定义一个新的计划任务。此时会出现一个向导界面,引导用户逐步完成任务的设定。 3. **选择任务类型** 当前支持多种任务类别,对于导出导入需求而言,应分别选取如下选项: - 导出:选择 “数据传输” 类型。 - 导入:同样可选 “数据传输”,只需调整源与目标的方向即可[^4]。 4. **指定数据范围** 接下来需明确哪些表或视图参与此次操作。可以通过勾选具体对象列表中的条目来进行精确控制;也可以采用通配符批量处理整个模式下的所有实体[^4]。 5. **设置存储路径** 对于导出作业来说,必须指明文件保存的位置及其格式(CSV, Excel, TXT 等)。而针对导入流程,则相反地需要提供原始资料所在地址以及匹配的目标结构[^4]。 6. **规划触发时间** 利用内嵌的日历控件配合时刻参数输入框,准确划定初次启动日期及时刻,并决定后续重复频率(每日、每周、每月或是自定义间隔)[^3]。 7. **高级属性定制** 如果必要的话,还可以进一步优化邮件通知机制、错误重试策略等方面的内容以增强可靠性。 8. **验证与激活** 最终审查各项参数无误之后提交确认,这样就成功建立了所期望的功能实例。记得启用开关使其生效[^4]。 ```bash # 示例命令行模拟手动测试脚本 (仅作参考用途) navicatcli --export source_db="my_database" target_file="/path/to/exported_data.csv" navicatcli --import source_file="/another/path/import_source.json" destination_table="new_records" ``` 以上便是利用 Navicat Premium 16 设置周期性数据迁移的基本步骤概述。实际应用当中可能还会涉及到更多细节考量因素,请参照官方文档获取最权威指导信息[^3]。 ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值