可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I am designing a Linux character device driver. I want to set errno when error occurs in ioctl() system call.
long my_own_ioctl(struct file *file, unsigned int req, unsigned long arg) { long ret = 0; BOOL isErr = FALSE; // some operation // ... if (isErr) { // set errno // ... <--- What should I do? ret = -1; } return ret; }
What should I do to achieve that? Thank you at advance!
Please allow me to explain my application with more detail.
My device is located in /dev/myCharDev. My user space application is like this:
#define _COMMAND (1) #define _ERROR_COMMAND_PARAMETER (-1) int main() { int fd = open("/dev/myCharDec", O_RDONLY); int errnoCopy; if (fd) { if (ioctl(fd, _COMMAND, _ERROR_COMMAND_PARAMETER) < 0) { // should cause error in ioctl() errnoCopy = errno; printf("Oops, error occurred: %s\n", strerr(errnoCopy)); // I want this "errno" printed correctly } close(fd); } return 0; }
As I mentioned in the comments above, How should I set the "errno" in my own device driver codes and make it readable by user space application?
回答1:
Nice question!
Ok, you could think of errno as global variable (to be honnest, it is an extern int). errno has plenty of pre-defined macros for errorcodes in the errno.h library. You can have a look here. It is very likely that some of these errorcodes describe what you want to show. Pick up the right one, set it like if it was a variable you defined, and (important!) exit immediately!
You may ask yourself though if setting errno is the right approach to your problem. You can always define an (*int) and develop your own error codes, and error handling mechanism. Errno's purpose is to show and explain system errors. Do u consider your code part of the "system" (as I can see you develop your own system call, so this might be the case) ? So go on and use errno to explain your "system error".
Edit (On question update): Ok more info. As i said errno is an extern int and is set by the kernel. The value at which errno is set is simply the return value of the system call. Linux kernel then interprets this negative value through the library errno.h. So an example error message is set simply by returning (EBUSY is just an example - you can use all of the predifined error types) the error message you want from your system call. Example:
return -EBUSY
Hope it helps
回答2:
Return the negative error number from the ioctl. The c library interprets this and gives a -1 return code and sets errno to the positive error. For instance your original example will set errno to 1.
As an aside your prototype for an ioctl function in the kernel looks wrong. Which kernel version are you using?
回答3:
if (isErr) { printk(KERN_ALERT "Error %d: your description\n", errno); ret = errno; }
where, errno
is the return value of some function.
Your device driver should always return a status for a request it received. It is advocated you always use enumerated return codes as well as normal return codes. Returning 0 = pass 1 or -1 = failed is vague and could be misleading.
Read section 3.1 Efficient error handling, reporting and recovery: for more information