Escolar Documentos
Profissional Documentos
Cultura Documentos
HOME
REVIEWS
HOW-TOS
CODING
INTERVIEWS
FEATURES
OVERVIEW
BLOGS
SERIES
IT ADMIN
Search for:
Search
This article, which is part of the series on Linux device drivers, talks about the typical ioctl() implementation and usage in Linux.
Get me a laptop, and tell me about the x86 hardware interfacing experiments in the last Linux device drivers lab session, and also about whats planned for the next session, cried Shweta, exasperated at being confined to bed due to food poisoning at a friends party. Shwetas friends summarised the session, and told her that they didnt know what the upcoming sessions, though related to hardware, would be about. When the doctor requested them to leave, they took the opportunity to plan and talk about the most common hardware-controlling operation, i o c t l ( ) .
Introducing ioctl()
Input/Output Control (ioctl, in short) is a common operation, or system call, available in most driver categories. It is a one-bill-fits-all kind of system call. If there is no other system call that meets a particular requirement, then i o c t l ( )is the one to use. Practical examples include volume control for an audio device, display configuration for a video device, reading device registers, and so on basically, anything to do with device input/output, or device-specific operations, yet versatile enough for any kind of operation (for example, for debugging a driver by querying driver data structures). The question is: how can all this be achieved by a single function prototype? The trick lies in using its two key parameters: command and argument. The command is a number representing an operation. The argument command is the corresponding parameter for the operation. The i o c t l ( )function implementation does a switch case over the commmand to implement the corresponding functionality. The following has been its prototype in the Linux kernel for quite some time:
i n ti o c t l ( s t r u c ti n o d e* i ,s t r u c tf i l e* f ,u n s i g n e di n tc m d ,u n s i g n e dl o n ga r g ) ;
Follow
+2,491
www.linuxforu.com/2011/08/io-control-in-linux/
1/8
8/12/13
If there is a need for more arguments, all of them are put in a structure, and a pointer to the structure becomes the one command argument. Whether integer or pointer, the argument is taken as a long integer in kernel-space, and accordingly type-cast and processed.
i o c t l ( )is typically implemented as part of the corresponding driver, and then an appropriate
function pointer is initialised with it, exactly as in other system calls like o p e n ( ) ,r e a d ( ) , etc. For example, in character drivers, it is the i o c t lor u n l o c k e d _ i o c t l(since kernel 2.6.35) function pointer field in the s t r u c tf i l e _ o p e r a t i o n sthat is to be initialised. Again, like other system calls, it can be equivalently invoked from user-space using the i o c t l ( ) system call, prototyped in < s y s / i o c t l . h >as:
i n ti o c t l ( i n tf d ,i n tc m d ,. . . ) ;
Here, c m dis the same as what is implemented in the drivers i o c t l ( ) , and the variable argument construct (. . . ) is a hack to be able to pass any type of argument (though only one) to the drivers i o c t l ( ) . Other parameters will be ignored. Note that both the command and command argument type definitions need to be shared across the driver (in kernel-space) and the application (in user-space). Thus, these definitions are commonly put into header files for each space.
Popular
Comments
Tag cloud
www.linuxforu.com/2011/08/io-control-in-linux/
2/8
8/12/13
4 7 4 8 4 9 5 0 5 1 5 2 5 3 5 4 5 5 5 6 5 7 5 8 5 9 6 0 6 1 6 2 6 3 6 4 6 5 6 6 6 7 6 8 6 9 7 0 7 1 7 2 7 3 7 4 7 5 7 6 7 7 7 8 7 9 8 0 8 1 8 2 8 3 8 4 8 5 8 6 8 7 8 8 8 9 9 0 9 1 9 2 9 3 9 4 9 5 9 6 9 7 9 8 9 9 1 0 0 1 0 1 1 0 2 1 0 3 1 0 4 1 0 5 1 0 6 1 0 7 1 0 8 1 0 9 1 1 0 1 1 1 1 1 2 1 1 3 1 1 4 1 1 5 1 1 6 1 1 7 1 1 8 1 1 9 1 2 0 1 2 1 1 2 2 1 2 3 1 2 4 1 2 5 1 2 6 1 2 7 1 2 8
} }
r e t u r n0 ;
s t a t i cs t r u c tf i l e _ o p e r a t i o n sq u e r y _ f o p s= { . o w n e r=T H I S _ M O D U L E , . o p e n=m y _ o p e n , . r e l e a s e=m y _ c l o s e , # i f( L I N U X _ V E R S I O N _ C O D E<K E R N E L _ V E R S I O N ( 2 , 6 , 3 5 ) ) . i o c t l=m y _ i o c t l # e l s e . u n l o c k e d _ i o c t l=m y _ i o c t l # e n d i f } ; s t a t i ci n t_ _ i n i tq u e r y _ i o c t l _ i n i t ( v o i d ) { i n tr e t ; s t r u c td e v i c e* d e v _ r e t ; i f( ( r e t=a l l o c _ c h r d e v _ r e g i o n ( & d e v ,F I R S T _ M I N O R ,M I N O R _ C N T ," q u e r y _ i o c t l " ) )<0 ) { r e t u r nr e t ; } c d e v _ i n i t ( & c _ d e v ,& q u e r y _ f o p s ) ; i f( ( r e t=c d e v _ a d d ( & c _ d e v ,d e v ,M I N O R _ C N T ) )<0 ) { r e t u r nr e t ; } i f( I S _ E R R ( c l=c l a s s _ c r e a t e ( T H I S _ M O D U L E ," c h a r " ) ) ) { c d e v _ d e l ( & c _ d e v ) ; u n r e g i s t e r _ c h r d e v _ r e g i o n ( d e v ,M I N O R _ C N T ) ; r e t u r nP T R _ E R R ( c l ) ; } i f( I S _ E R R ( d e v _ r e t=d e v i c e _ c r e a t e ( c l ,N U L L ,d e v ,N U L L ," q u e r y " ) ) ) { c l a s s _ d e s t r o y ( c l ) ; c d e v _ d e l ( & c _ d e v ) ; u n r e g i s t e r _ c h r d e v _ r e g i o n ( d e v ,M I N O R _ C N T ) ; r e t u r nP T R _ E R R ( d e v _ r e t ) ; } } r e t u r n0 ;
And finally, the corresponding invocation functions from the application q u e r y _ a p p . cwould be as follows:
1 2 3 4 5 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 # i n c l u d e< s t d i o . h > # i n c l u d e< s y s / t y p e s . h > # i n c l u d e< f c n t l . h > # i n c l u d e< u n i s t d . h > # i n c l u d e< s t r i n g . h > # i n c l u d e< s y s / i o c t l . h > # i n c l u d e" q u e r y _ i o c t l . h " v o i dg e t _ v a r s ( i n tf d ) { q u e r y _ a r g _ tq ; i f( i o c t l ( f d ,Q U E R Y _ G E T _ V A R I A B L E S ,& q )= =1 ) { p e r r o r ( " q u e r y _ a p p si o c t lg e t " ) ; } e l s e { p r i n t f ( " S t a t u s:% d \ n " ,q . s t a t u s ) ;
www.linuxforu.com/2011/08/io-control-in-linux/
3/8
8/12/13
2 1 2 2 2 3 2 4 2 5 2 6 2 7 2 8 2 9 3 0 3 1 3 2 3 3 3 4 3 5 3 6 3 7 3 8 3 9 4 0 4 1 4 2 4 3 4 4 4 5 4 6 4 7 4 8 4 9 5 0 5 1 5 2 5 3 5 4 5 5 5 6 5 7 5 8 5 9 6 0 6 1 6 2 6 3 6 4 6 5 6 6 6 7 6 8 6 9 7 0 7 1 7 2 7 3 7 4 7 5 7 6 7 7 7 8 7 9 8 0 8 1 8 2 8 3 8 4 8 5 8 6 8 7 8 8 8 9 9 0 9 1 9 2 9 3 9 4 9 5 9 6 9 7 9 8 9 9 1 0 0 1 0 1 1 0 2 1 0 3 1 0 4 1 0 5 1 0 6 1 0 7 1 0 8 1 0 9 1 1 0 1 1 1 1 1 2 1 1 3 1 1 4 1 1 5 1 1 6 1 1 7 1 1 8 1 1 9 1 2 0 1 2 1
i n tm a i n ( i n ta r g c ,c h a r* a r g v [ ] ) { c h a r* f i l e _ n a m e=" / d e v / q u e r y " ; i n tf d ; e n u m { e _ g e t , e _ c l r , e _ s e t }o p t i o n ; i f( a r g c= =1 ) { o p t i o n=e _ g e t ; } e l s ei f( a r g c= =2 ) { i f( s t r c m p ( a r g v [ 1 ] ," g " )= =0 ) { o p t i o n=e _ g e t ; } e l s ei f( s t r c m p ( a r g v [ 1 ] ," c " )= =0 ) { o p t i o n=e _ c l r ; } e l s ei f( s t r c m p ( a r g v [ 1 ] ," s " )= =0 ) { o p t i o n=e _ s e t ; } e l s e { f p r i n t f ( s t d e r r ," U s a g e :% s[ g|c|s ] \ n " ,a r g v [ 0 ] ) ; r e t u r n1 ; } } e l s e { f p r i n t f ( s t d e r r ," U s a g e :% s[ g|c|s ] \ n " ,a r g v [ 0 ] ) ; r e t u r n1 ; } f d=o p e n ( f i l e _ n a m e ,O _ R D W R ) ; i f( f d= =1 ) { p e r r o r ( " q u e r y _ a p p so p e n " ) ; r e t u r n2 ; } s w i t c h( o p t i o n ) { c a s ee _ g e t : g e t _ v a r s ( f d ) ; b r e a k ; c a s ee _ c l r : c l r _ v a r s ( f d ) ; b r e a k ; c a s ee _ s e t : s e t _ v a r s ( f d ) ; b r e a k ; d e f a u l t : b r e a k ; } c l o s e( f d ) ; } r e t u r n0 ;
Now try out q u e r y _ a p p . cand q u e r y _ i o c t l . cwith the following operations: Build the q u e r y _ i o c t ldriver (q u e r y _ i o c t l . k ofile) and the application (q u e r y _ a p pfile) by running m a k e , using the following M a k e f i l e :
www.linuxforu.com/2011/08/io-control-in-linux/
4/8
8/12/13
1 2 3 4 5 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1
Load the driver using i n s m o dq u e r y _ i o c t l . k o . With appropriate privileges and command-line arguments, run the application q u e r y _ a p p :
. / q u e r y _ a p p to display the driver variables . / q u e r y _ a p pc to clear the driver variables . / q u e r y _ a p pg to display the driver variables . / q u e r y _ a p ps to set the driver variables (not mentioned above)
command. Just that, now additionally, some useful command related information is also encoded as part of these numbers using various macros, as per the POSIX standard for i o c t l . The standard talks about the 32-bit command numbers, formed of four components embedded into the [31:0] bits: 1. The direction of command operation [bits 31:30] -- read, write, both, or none -- filled by the corresponding macro (_ I O R ,_ I O W ,_ I O W R ,_ I O ). 2. The size of the command argument [bits 29:16] -- computed using s i z e o f ( )with the command argument's type -- the third argument to these macros. 3. The 8-bit magic number [bits 15:8] -- to render the commands unique enough -- typically an ASCII character (the first argument to these macros). 4. The original command number [bits 7:0] -- the actual command number (1, 2, 3, ...), defined as per our requirement -- the second argument to these macros. Check out the header < a s m g e n e r i c / i o c t l . h >for implementation details.
Related Posts:
Device Drivers, Part 5: Character Device Files Creation & Operations Device Drivers, Part 7: Generic Hardware Access in Linux Device Drivers, Part 6: Decoding Character Device File Operations Device Drivers, Part 17: Module Interactions Working with MTD Devices
Tags: ASCII, data structures, device input, driver, drivers, I/O, input output, ioctl, kernel space, LFY August 2011, Linux, linux device drivers, Linux Device Drivers Series, Linux kernel, long ar, POSIX, registers, struct inode, switch case, system call, unsigned int, userspace, x86 hardware
Previous Post
Next Post
www.linuxforu.com/2011/08/io-control-in-linux/
5/8
8/12/13
Connecting to MySQL with Python and PHP
What's this?
OpenMP Schedule Clause Parallel Matrix Multiplication 7 months ago Getting Your First Job Code Sport
1 comment 1 comment
Pastor Reveals 7 Shocking Biblical Truths on Investing Moneynews Don't Get Alzheimer's: Here's What May Cause It Newsmax Health Protect Yourself in a Divorce: 9 Things You Must Do Citi Women & Co. A Beauty Guru's Secret Weapons
DailyCandy
Share
14 days ago
For Latest Kernels use the following Makefile #3.7.10-1.16 # If called directly from the command line, invoke the kernel build system. ifeq ($(KERNELRELEASE),) # KERNEL_SOURCE := /usr/src/linux KERNEL_SOURCE := /lib/modules/$(shell uname -r)/build PWD := $(shell pwd) default: module query_app #make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules module: $(MAKE) -C $(KERNEL_SOURCE) SUBDIRS=$(PWD) modules
see more
Reply
Share
anil_pugalia
> Eshwar
14 days ago
dhanamjay a
It is nothing to do with latest kernels. It's how the kernel source/headers are organized in your particular disto. In fact, this file would work with previous versions of kernel as well.
Reply Share
19 days ago
anil_pugalia
> dhanamjaya
Share
19 days ago
6 months ago
Reply
Share
anil_pugalia
6 months ago
Reply
A nand
8 months ago
Great article..Understood lots of things..simple prgrm explanation,now evn i can start www.linuxforu.com/2011/08/io-control-in-linux/
6/8
8/12/13
John
Device Drivers, Part 9: I/O Control in Linux - LINUX For You Great article..Understood lots of things..simple prgrm explanation,now evn i can start to write my own in better manner..thanks..i would like to get these type of DD explanation more n more..:-)
Reply Share
8 months ago
Hi sir, I want to write a module that returns inode of specific file ,so how can i code it to get inode of particular file?
Reply Share
anil_pugalia
> John
8 months ago
You do not really need to write a module for that. You may use the already available system call "lstat".
Reply John Share
> anil_pugalia
8 months ago
Thanks for the reply Sir, Now i want to trace the code of inode & ioctl files of ext4 using printk statements for better understanding there working.How can i do that whether i need to recomplie kernel?
Reply Share
anil_pugalia
> John
8 months ago
Rama
If ext4 is compiled as a module, you do not need to recompile the kernel, but just recompile the module; otherwise recompile the kernel by making ext4 as module and then follow the above step.
Reply Share
8 months ago
Hi Anil, Really these articles are very useful to start up. I have one query on open call. in open system call if we give device file name as input it finally interact with that device_open function in driver. if we look at device_open syntax, the first parameter is struct inode*. The struct inode* internally has i_cdev, by using macros we can get major and minor number. The question is how your device file name linked to driver open function?. how device file name in open system call identifies the major number?. After sucess it returns file descriptor. I know the sequence once we got file descriptor how it interact with file structure. Could you please explain how open system call internally works from user space to till kernel space, not with respect to general system call execution, with respect to device file name to driver_open flow
Reply Share
anil_pugalia
> Rama
8 months ago
user space open call with the file name goes to VFS, which checks out the inode of the file, based on its absolute path, thus populating the struct inode for it. And then creates a struct file based on that, and then it invokes the driver_open (the actual system call), with both of these as the parameters. On success of the same, a per-process free file descriptor (integer) is allotted and returned back to the user. Hope that clarifies your doubt. In short, VFS is the key translator.
1 foc us
Reply
Share
9 months ago
I enjoy reading your tutorial.. Thanks for keeping it simple and clear. Keep up the good work.
Reply Share
anil_pugalia
> focus
8 months ago
S ent hil
10 months ago
Really excellent work ,i have read so many books for understanding "ioctl" but
www.linuxforu.com/2011/08/io-control-in-linux/ 7/8
8/12/13
everybody explains it as a toughest thing in Device drivers but you are outstanding in explaining it in a simple way.
Reply Share
anil_pugalia
> Senthil
8 months ago
rak es h
11 months ago
I became fan of you for your generosity to take time and explain so greatly. Thank you
Reply Share
A nil P ugalia
> rakesh
11 months ago
anil_pugalia 1
Share
Reply
Share
das t agir 1
a year ago
C o m m e n t fe e d
Su b s cri b e vi a e m a i l
Reviews
How-Tos
Coding
Interviews
Features
Overview
Blogs
Search
Popular tags
Linux , ubuntu, Java, MySQL, Google, python, Fedora, Android, PHP, C, html, w eb applications , India, Microsoft, unix , Window s , Red Hat, Oracle, Security , Apache, xml, LFY April 2012, FOSS, GNOME, http, JavaScript, LFY June 2011, open source, RAM, operating systems
All published articles are released under Creative Commons Attribution-NonCommercial 3.0 Unported License, unless otherw ise noted. LINUX For You is pow ered by WordPress, w hich gladly sits on top of a CentOS-based LEMP stack.
www.linuxforu.com/2011/08/io-control-in-linux/
8/8