简体   繁体   中英

kstrtoint in sysfs for c kernel module

Hi I am trying to use a kobject to write to a int array from sysfs. So the input is a char* and a size variable. I cant seem to get this to work however. My expected input is "num1 num2 num3 "

static ssize_t pids_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) {

int num_count = 0;
int i = 0;
int result = 0;
int cur_pid = 0;
char *dst;
char *ddst;

printk(KERN_INFO "GPIO_DEGUG: enter");

dst = buf;
ddst = buf;

printk(KERN_INFO "GPIO_DEGUG:  size of buffer %d ",count);


while(ddst < (buf + sizeof(size_t)*count)) {
ddst ++;
if (ddst[0] == ' ') {
   result = kstrtoint(dst,10,&cur_pid);
   dst=ddst+1;

   printk(KERN_INFO "GPIO_DEGUG: kstrtoint suceeded %d ",cur_pid);
   printk(KERN_INFO "GPIO_DEGUG: kstrtoint suceeded res: %d ",result);
   pids[num_count] = cur_pid;
   num_count += 1;
   }
}

for(i=0;i<num_count;i++) {
    printk(KERN_INFO "GPIO_TEST: pid: %d \n", pids[i]);
}
printk(KERN_INFO "GPIO_DEBUG: leaving\n");
return count;                                         
}

When I echo "100 " > /sys/vt/vt7/pids I get

[ 2765.712770] GPIO_DEGUG: enter 
[ 2765.724468] GPIO_DEGUG:  size of buffer 5 
[ 2765.735101] GPIO_DEGUG: kstrtoint suceeded 0 
[ 2765.746526] GPIO_DEGUG: kstrtoint suceeded res: -22 
[ 2765.757746] GPIO_DEBUG: leaving 

I suppose this is an argument error any help would be nice, thanks.

Function kstrtoint expects full string to contain single integer value . The only exception is a newline character at the end of the string:

The string must be null-terminated, and may also include a single newline before its terminating null.

As you can see, string "100 " doesn't fit for that requirement: it contains exceeded space.

For parse only part of the string as an integer, you may use simple_strtol :

long val = simple_strtol(dst, &ddst, 10);
if(ddst == ddst) {/* Parsing has been failed. */};

While this function is marked as an obsolete, there is still some code in the kernel which uses it.

Another possibility is to use sscanf . It expects fixed number of integers in the string, but it is an usual situation with attributes: having complex representation of the attributes is not recommended :

The conventions for sysfs state that each attribute should contain a single, human-readable value; if you have a lot of information to return, you may want to consider splitting it into multiple attributes.

( Linux Device Drivers 3, chapter 14 ).

The kstrtoint function is defined here:

http://lxr.free-electrons.com/source/lib/kstrtox.c#L245

If you notice the last value of *res defined in the function is the value you wish to use. In your case cur_pid should be the value in which you want to print, the result should always be zero if it was successful. I would suggest checking result to make sure that the conversion has succeeded.

This should work:

int cur_pid, result;
char *dst = NULL;

cur_pid = result = 0;
dst = buf;

result = kstrtoint(dst, 10, &cur_pid);
if (result)
     printk(KERN_INFO "GPIO_DEGUG: kstrtoint suceeded res: %d ", cur_pid);
else
     printk(KERN_INFO "ERROR");

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM