如何在Linux内核中将char 字符串转换为int?

如何在linux内核中将char []转换为int

validation输入的文本实际上是一个int?

int procfile_write(struct file *file, const char *buffer, unsigned long count, void *data) { char procfs_buffer[PROCFS_MAX_SIZE]; /* get buffer size */ unsigned long procfs_buffer_size = count; if (procfs_buffer_size > PROCFS_MAX_SIZE ) { procfs_buffer_size = PROCFS_MAX_SIZE; } /* write data to the buffer */ if ( copy_from_user(procfs_buffer, buffer, procfs_buffer_size) ) { return -EFAULT; } int = buffer2int(procfs_buffer, procfs_buffer_size); return procfs_buffer_size; } 

在友好的linux源代码树中查看#include kstrtol()的各种forms。

您需要哪一个取决于*buffer是用户还是内核地址,以及您对error handling/检查缓冲区内容的需求有多严格(例如, 123qx无效还是应该返回123 ?)。

由于linux内核中没有很多常用的函数/宏,你不能使用任何直接函数从字符串缓冲区中获取整数值。

这是我长期使用的代码,它可用于所有* NIX风格(可能没有任何修改)。

这是修改后的代码forms,我从开源项目中使用了很长时间(现在不记得名字了)。

 #define ISSPACE(c) ((c) == ' ' || ((c) >= '\t' && (c) <= '\r')) #define ISASCII(c) (((c) & ~0x7f) == 0) #define ISUPPER(c) ((c) >= 'A' && (c) <= 'Z') #define ISLOWER(c) ((c) >= 'a' && (c) <= 'z') #define ISALPHA(c) (ISUPPER(c) || ISLOWER(c)) #define ISDIGIT(c) ((c) >= '0' && (c) <= '9') unsigned long mystr_toul ( char* nstr, char** endptr, int base) { #if !(defined(__KERNEL__)) return strtoul (nstr, endptr, base); /* user mode */ #else char* s = nstr; unsigned long acc; unsigned char c; unsigned long cutoff; int neg = 0, any, cutlim; do { c = *s++; } while (ISSPACE(c)); if (c == '-') { neg = 1; c = *s++; } else if (c == '+') c = *s++; if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X')) { c = s[1]; s += 2; base = 16; } if (base == 0) base = c == '0' ? 8 : 10; cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; cutlim = (unsigned long)ULONG_MAX % (unsigned long)base; for (acc = 0, any = 0; ; c = *s++) { if (!ISASCII(c)) break; if (ISDIGIT(c)) c -= '0'; else if (ISALPHA(c)) c -= ISUPPER(c) ? 'A' - 10 : 'a' - 10; else break; if (c >= base) break; if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) any = -1; else { any = 1; acc *= base; acc += c; } } if (any < 0) { acc = INT_MAX; } else if (neg) acc = -acc; if (endptr != 0) *((const char **)endptr) = any ? s - 1 : nstr; return (acc); #endif } 

最小的可运行的kstrtoull_from_user debugfs示例

处理用户数据时, kstrto*_from_user系列非常方便。

kstrto.c:

 #include  #include  #include  #include  /* S_IRUSR */ static struct dentry *toplevel_file; static ssize_t write(struct file *filp, const char __user *buf, size_t len, loff_t *off) { int ret; unsigned long long res; ret = kstrtoull_from_user(buf, len, 10, &res); if (ret) { /* Negative error code. */ pr_info("ko = %d\n", ret); return ret; } else { pr_info("ok = %llu\n", res); *off= len; return len; } } static const struct file_operations fops = { .owner = THIS_MODULE, .write = write, }; static int myinit(void) { toplevel_file = debugfs_create_file("lkmc_kstrto", S_IWUSR, NULL, NULL, &fops); if (!toplevel_file) { return -1; } return 0; } static void myexit(void) { debugfs_remove(toplevel_file); } module_init(myinit) module_exit(myexit) MODULE_LICENSE("GPL"); 

用法:

 insmod kstrto.ko cd /sys/kernel/debug echo 1234 > lkmc_kstrto echo foobar > lkmc_kstrto 

Dmesg输出:

 ok = 1234 ko = -22 

使用此QEMU + Buildroot设置在Linux内核4.16中进行了测试。

对于此特定示例,您可能希望使用debugfs_create_u32

使用atoi和isdigit(注意isdigit只需要一个字符)。 http://www.cplusplus.com/reference/clibrary/cctype/isdigit/

我使用sscanf()(内核版本)从字符串流中扫描,它适用于2.6.39-gentoo-r3。 坦率地说,我永远无法让simple_strtol()在内核中工作 – 我目前正在弄清楚为什么这在我的盒子上不起作用。

  ... memcpy(bufActual, calc_buffer, calc_buffer_size); /* a = simple_strtol(bufActual, NULL, 10); */ // Could not get this to work sscanf(bufActual, "%c%ld", &opr, &a); // places '+' in opr and a=20 for bufActual = "20+\0" ...