如何在Linux内核空间中从字符串中提取整数?

3
我希望从字符串中提取整数,例如我想从字符串“/dev/nkdev/group0/mdev1”中提取0作为组标识符,提取1作为mdev标识符。
在上述字符串中,“/dev/nkdev/group”是输入的固定模式,组ID可以是0-9之间的任何整数,“mdev”也不是固定的,它可以是任何字符序列,后跟一个整数。
我使用了以下代码:
#define NO_INTEGER "%0[^0-9]"

res = sscanf(dev_name_p, NO_INTEGER "%u" NO_INTEGER "%u",
             &group_id, &mdev_id);

但是我发现内核不支持跳过序列。有没有人能告诉我,是否有任何内核库函数可以完成这项工作?


使用格式 /dev/nkdev/group%u/mdev%u 不是有可能吗? - bzeaman
谢谢,如果mdev是一个固定的模式,那么这是可能的。但在我的情况下,mdev也不是固定的,它可以是任何字符序列。 - Cool Goose
2
那么/dev/nkdev/group%u/%*s%u呢? - bzeaman
@bzeaman 这应该是被采纳的答案,你应该发布一下! - Ishay Peled
@IshayPeled 这个方法不起作用,我后来发现。%*s也包括了紧随着mdev部分的数字。在他的问题中,他声明不支持“跳过序列”,我认为他指的是像%*[a-z]这样的格式。无论如何,我还是发布了这个答案,它可能会帮助其他人。 - bzeaman
乍一看,在内核中解析这样的字符串时,您可能会做错事情。是否有其他方法可以获取这些整数?如果仍然是这种情况,您必须使用 simple_strtoul() 和自己的循环来解析其中的所有数字。 - 0andriy
3个回答

3

kstrtoint() — 将字符串转换为整数。

kstrtol() — 将字符串转换为长整型。

您可以在 Linux 内核源代码树中检查声明 /include/linux/kernel.h。在使用此函数之前,您需要包含此头文件 #include< linux/kernel.h>

 Example :

    const char *buf = "123";
    long value;
    if(kstrtoint(buf, 10, &value) != 0)
         return -1;
     printk("%d",value);

这对于不仅由数字组成的字符串无效,使用“/dev/nkdev/group1/mdev2”测试您的解决方案。 - Ishay Peled
这确实不起作用,也没有回答问题。 - bzeaman

2
我使用的格式字符串应该可以工作:
#include <stdio.h>

int main(void)
{
        unsigned a = 38, b = 38; // Default magic value
        int n = sscanf("/dev/nkdev/group0/abc1", "/dev/nkdev/group%u/%*[a-z]%u", &a, &b);

        printf("n: %i, a: %u, b: %u\n", n, a, b);

        return 0;
}

它会产生以下输出:
n: 2, a: 0, b: 1

这应该是被接受的答案,快速、简单并且适用于所有情况。 - Ishay Peled
在Linux内核空间中,'%*[a-z]'序列格式化不受支持,因此它无法正常工作。我在我的代码中使用了类似的方法,在libc中可以正常工作,但在内核空间中无法正常工作。 - Cool Goose

-2
这个解决方案在用户空间运行,但这里使用的所有函数在内核空间中也都可以得到相同的结果。
比较hack的方法,但它能起作用:
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <stdio.h>

int main(int argc, char **argv)
{
    char string[] = "/dev/nkdev/group4/mdev12";
    char *stringp = (char *)&string;
    const char delimiters[] = "/";
    char *token;
    int num1, num2;

    token = strsep (&stringp, delimiters);        /* token => "" */
    token = strsep (&stringp, delimiters);        /* token => "dev" */
    token = strsep (&stringp, delimiters);        /* token => "nkdev" */
    token = strsep (&stringp, delimiters);        /* token => "group0" */
    while (*token != 0 && (*token < '0' || *token > '9'))
        token++;
    num1 = strtol(token, NULL, 10);
    token = strsep (&stringp, delimiters);        /* token => "mdev1" */
    while (*token != 0 && (*token < '0' || *token > '9'))
        token++;
    num2 = strtol(token, NULL, 10);
    printf("num1: %d\nnum2: %d\n", num1, num2);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接