Android环境下使用call_usermodehelper()以及调试

本文介绍如何在Linux内核态下通过call_usermodehelper()调用用户态程序,并解析该函数的参数意义及常见错误码。当遇到Permission denied错误时,需考虑SELinux机制的影响。

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

有时候设备驱动需要做一些与其他的设备通信的操作,但是驱动本身又不可以去实作,那这个时候就可以通过调用用户态的软件,通过这个软件和其他的设备进行通信。

那在内核态如何去调用用户态的程序呢?call_usermodehelper() 可以做到。这个linux kernel提供的一个接口,并且这个程序具体root 权限。

这个函数的调用的方法是非常简单的。如下:

    char cmd_path[] = "/vendor/bin/XX";
    char* cmd_argv_low[] = {cmd_path,"wlan0","write","xxxx",NULL};
    char* cmd_envp[] = {"PATH=/sbin:/system/bin", NULL};
    int touch_int = 0;
    touch_int = call_usermodehelper(cmd_path, cmd_argv_low, cmd_envp, UMH_WAIT_EXEC);
        printk(KERN_DEBUG "call_usermodehelper is %d \n", touch_int);             

 

如果顺利执行,上面的代码相当于在shell中执行了 /vendor/bin/XX wlan0 write xxxx  这么一条指令。下面简单解释一下 各个参数的意思:

  1. cmd_path  就是这个用户态的程序存放的位置。
  2. cmd_argv_low 是传给用户态程序的参数列表,相当于argv[0],argv[1],最后要以NULL 结尾
  3. cmd_envp 是传给程序的环境变量,同样也要以NULL 结尾
  4. 最后如果执行成功,那么返回0

但是当我执行这段程序的时候,并没有返回0,而是返回了-13,搜索了一下linux 内核关于错误码的定义,发现是Permission denied ,程序是root权限为什么还是会是权限不通过呢?原来是Android 有selinux 机制挡掉了这次调用。

暂时关闭selinux机制就可以使用了,当然要彻底解决的话,就要通过添加te 规则来通过Android的安全检查。

这里顺便也列一下kernel 的常见的错误码:

#define EPERM   1 /* Operation not permitted */
#define ENOENT   2 /* No such file or directory */
#define ESRCH   3 /* No such process */
#define EINTR   4 /* Interrupted system call */
#define EIO   5 /* I/O error */
#define ENXIO   6 /* No such device or address */
#define E2BIG   7 /* Argument list too long */
#define ENOEXEC   8 /* Exec format error */
#define EBADF   9 /* Bad file number */
#define ECHILD  10 /* No child processes */
#define EAGAIN  11 /* Try again */
#define ENOMEM  12 /* Out of memory */
#define EACCES  13 /* Permission denied */
#define EFAULT  14 /* Bad address */
#define ENOTBLK  15 /* Block device required */
#define EBUSY  16 /* Device or resource busy */
#define EEXIST  17 /* File exists */
#define EXDEV  18 /* Cross-device link */
#define ENODEV  19 /* No such device */
#define ENOTDIR  20 /* Not a directory */
#define EISDIR  21 /* Is a directory */
#define EINVAL  22 /* Invalid argument */
#define ENFILE  23 /* File table overflow */
#define EMFILE  24 /* Too many open files */
#define ENOTTY  25 /* Not a typewriter */
#define ETXTBSY  26 /* Text file busy */
#define EFBIG  27 /* File too large */
#define ENOSPC  28 /* No space left on device */
#define ESPIPE  29 /* Illegal seek */
#define EROFS  30 /* Read-only file system */
#define EMLINK  31 /* Too many links */
#define EPIPE  32 /* Broken pipe */
#define EDOM  33 /* Math argument out of domain of func */
#define ERANGE  34 /* Math result not representable */
#define EDEADLK  35 /* Resource deadlock would occur */
#define ENAMETOOLONG 36 /* File name too long */
#define ENOLCK  37 /* No record locks available */
#define ENOSYS  38 /* Function not implemented */
#define ENOTEMPTY 39 /* Directory not empty */
#define ELOOP  40 /* Too many symbolic links encountered */
#define EWOULDBLOCK EAGAIN /* Operation would block */
#define ENOMSG  42 /* No message of desired type */
#define EIDRM  43 /* Identifier removed */
#define ECHRNG  44 /* Channel number out of range */
#define EL2NSYNC 45 /* Level 2 not synchronized */
#define EL3HLT  46 /* Level 3 halted */
#define EL3RST  47 /* Level 3 reset */
#define ELNRNG  48 /* Link number out of range */
#define EUNATCH  49 /* Protocol driver not attached */
#define ENOCSI  50 /* No CSI structure available */
#define EL2HLT  51 /* Level 2 halted */
#define EBADE  52 /* Invalid exchange */
#define EBADR  53 /* Invalid request descriptor */
#define EXFULL  54 /* Exchange full */
#define ENOANO  55 /* No anode */
#define EBADRQC  56 /* Invalid request code */
#define EBADSLT  57 /* Invalid slot */

#define EDEADLOCK EDEADLK

#define EBFONT  59 /* Bad font file format */
#define ENOSTR  60 /* Device not a stream */
#define ENODATA  61 /* No data available */
#define ETIME  62 /* Timer expired */
#define ENOSR  63 /* Out of streams resources */
#define ENONET  64 /* Machine is not on the network */
#define ENOPKG  65 /* Package not installed */
#define EREMOTE  66 /* Object is remote */
#define ENOLINK  67 /* Link has been severed */
#define EADV  68 /* Advertise error */
#define ESRMNT  69 /* Srmount error */
#define ECOMM  70 /* Communication error on send */
#define EPROTO  71 /* Protocol error */
#define EMULTIHOP 72 /* Multihop attempted */
#define EDOTDOT  73 /* RFS specific error */
#define EBADMSG  74 /* Not a data message */
#define EOVERFLOW 75 /* Value too large for defined data type */
#define ENOTUNIQ 76 /* Name not unique on network */
#define EBADFD  77 /* File descriptor in bad state */
#define EREMCHG  78 /* Remote address changed */
#define ELIBACC  79 /* Can not access a needed shared library */
#define ELIBBAD  80 /* Accessing a corrupted shared library */
#define ELIBSCN  81 /* .lib section in a.out corrupted */
#define ELIBMAX  82 /* Attempting to link in too many shared libraries */
#define ELIBEXEC 83 /* Cannot exec a shared library directly */
#define EILSEQ  84 /* Illegal byte sequence */
#define ERESTART 85 /* Interrupted system call should be restarted */
#define ESTRPIPE 86 /* Streams pipe error */
#define EUSERS  87 /* Too many users */
#define ENOTSOCK 88 /* Socket operation on non-socket */
#define EDESTADDRREQ 89 /* Destination address required */
#define EMSGSIZE 90 /* Message too long */
#define EPROTOTYPE 91 /* Protocol wrong type for socket */
#define ENOPROTOOPT 92 /* Protocol not available */
#define EPROTONOSUPPORT 93 /* Protocol not supported */
#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
#define EPFNOSUPPORT 96 /* Protocol family not supported */
#define EAFNOSUPPORT 97 /* Address family not supported by protocol */
#define EADDRINUSE 98 /* Address already in use */
#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
#define ENETDOWN 100 /* Network is down */
#define ENETUNREACH 101 /* Network is unreachable */
#define ENETRESET 102 /* Network dropped connection because of reset */
#define ECONNABORTED 103 /* Software caused connection abort */
#define ECONNRESET 104 /* Connection reset by peer */
#define ENOBUFS  105 /* No buffer space available */
#define EISCONN  106 /* Transport endpoint is already connected */
#define ENOTCONN 107 /* Transport endpoint is not connected */
#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
#define ETOOMANYREFS 109 /* Too many references: cannot splice */
#define ETIMEDOUT 110 /* Connection timed out */
#define ECONNREFUSED 111 /* Connection refused */
#define EHOSTDOWN 112 /* Host is down */
#define EHOSTUNREACH 113 /* No route to host */
#define EALREADY 114 /* Operation already in progress */
#define EINPROGRESS 115 /* Operation now in progress */
#define ESTALE  116 /* Stale NFS file handle */
#define EUCLEAN  117 /* Structure needs cleaning */
#define ENOTNAM  118 /* Not a XENIX named type file */
#define ENAVAIL  119 /* No XENIX semaphores available */
#define EISNAM  120 /* Is a named type file */
#define EREMOTEIO 121 /* Remote I/O error */
#define EDQUOT  122 /* Quota exceeded */

#define ENOMEDIUM 123 /* No medium found */
#define EMEDIUMTYPE 124 /* Wrong medium type */

 


 

转载于:https://www.cnblogs.com/libs-liu/p/9330486.html

<think>好的,我现在需要解决用户关于全志芯片中call_usermodehelper函数的使用或错误的问题。首先,我得理解用户的需求。用户可能是在开发调试全志芯片的驱动或内核模块时遇到了问题,特别是涉及到call_usermodehelper这个函数的使用错误或者配置问题。 首先,我应该回忆一下call_usermodehelper的作用。它是Linux内核中的一个函数,用于从内核空间启动用户空间的应用程序。这在需要执行用户态任务时非常有用,比如加载固件、执行特定脚本等。但在使用过程中,可能会遇到权限问题、路径设置错误或者环境配置不正确的情况。 接下来,我需要考虑全志芯片的特殊性。全志芯片通常用于嵌入式系统,比如平板电脑、开发板等,其内核可能经过定制,可能会有不同的配置或补丁。因此,用户的问题可能与全志特定的内核配置有关,比如内核编译选项是否启用了相关的支持,或者是否存在特定的安全限制。 用户提到的错误可能有多种原因。例如,调用call_usermodehelper时返回权限错误,可能是因为内核配置中未启用CONFIG_STATIC_USERMODEHELPER,或者路径设置不正确。另外,SELinux或AppArmor等安全模块可能会阻止用户模式助手的执行,导致失败。 我需要分步骤来解答。首先,检查内核配置,确保相关的选项已经启用。然后,确认调用函数时的参数是否正确,比如二进制文件的路径是否绝对,权限是否设置正确。接着,查看内核日志,使用dmesg或journalctl来获取详细的错误信息,这有助于诊断问题。 另外,全志的SDK或BSP可能有特定的文档或示例代码,用户可以查阅这些资料,看看是否有关于call_usermodehelper的最佳实践或已知问题。如果用户没有这些文档,可能需要建议他们联系全志的技术支持,或者查看社区论坛是否有类似的问题讨论。 用户可能需要示例代码来说明如何正确使用call_usermodehelper。例如,正确的路径设置,参数传递方式,以及如何处理异步或同步调用。此外,错误处理也是关键,比如检查返回值,处理可能的错误代码。 在安全方面,嵌入式系统通常对内核到用户空间的交互有严格限制,特别是在生产环境中。用户可能需要调整安全策略,或者在内核模块中增加适当的权限。同时,考虑使用替代方案,比如工作队列或内核线程,如果call_usermodehelper不可行的话。 最后,我应该总结常见的解决步骤,并提供进一步排查的建议,比如检查内核配置、查看日志、调整安全设置等。如果用户遇到特定错误,如-EPERM或-ENOENT,需要分别针对权限或路径问题进行解答。 总结来说,我需要提供结构化的回答,涵盖使用方法、常见错误及解决方案,并引导用户进行逐步排查,同时考虑到全志芯片的特殊环境可能带来的额外因素。</think>关于全志芯片平台中$call\_usermodehelper$函数的使用及问题排查,以下是系统级开发的关键要点: ### 一、$call\_usermodehelper$基础用法 该函数用于在内核空间触发用户空间程序执行,常用于固件加载、热插拔事件处理等场景。典型调用方式: ```c static char *envp[] = { "PATH=/sbin:/bin", NULL }; char *argv[] = { "/usr/bin/my_helper", "param1", NULL }; int ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC); ``` 需特别注意: 1. 必须使用**绝对路径**指定可执行文件 2. 目标文件需具有可执行权限(建议$chmod +x$) 3. 环境变量需显式设置$PATH$[^1] ### 二、全志平台常见问题排查 #### 1. 权限拒绝错误(-EPERM) ```dmesg [ 123.456] usermodehelper: failed to execute /usr/bin/loader (errno:13) ``` 解决方案: - 检查内核配置$CONFIG_STATIC_USERMODEHELPER$是否启用 - 确认$CONFIG_UEVENT_HELPER_PATH$设置正确路径 - 禁用SELinux/AppArmor或添加策略例外 #### 2. 路径查找失败(-ENOENT) ```dmesg [ 234.567] usermodehelper: cannot find path "/system/bin/helper" ``` 处理方法: - 使用$ls -l /proc/sys/fs/uevent_helper$验证当前helper路径 - 在内核启动参数添加$uevent_helper=/sbin/hotplug$ #### 3. 异步调用阻塞 全志H5/H6平台需注意: ```c // 错误方式(可能导致调度异常) ret = call_usermodehelper(argv[0], argv, envp, UMH_NO_WAIT); // 推荐方式 ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC); ``` ### 三、全志SDK特殊配置 在Tina Linux等全志定制系统中,需修改以下文件: 1. `linux-*/security/Kconfig` 添加: ```kconfig config ALLWINNER_USERMODE_HELPER bool "Allwinner usermode helper support" default y ``` 2. 修改`init.sunxi.rc`确保用户空间服务就绪: ```rc on early-init start ueventd on property:sys.boot_completed=1 exec /system/bin/helper_daemon ``` ### 四、替代方案建议 当遇到不可解决的权限问题时,可考虑: 1. 改用$kthread_run$创建内核线程 2. 通过netlink实现内核-用户空间通信 3. 使用sysfs触发用户空间轮询
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值