Наши партнеры

UnixForum





Библиотека сайта rus-linux.net

На главную -> MyLDP -> Электронные книги по ОС Linux
Цилюрик О.И. Модули ядра Linux
Назад Внешние интерфейсы модуля Вперед

Управляющие операции устройства

Здесь (архив ioctl.tgz), для реализации уже знакомых нам операций регистрации устройства, мы умышленно воспользуемся, так называемым, старым методом регистрации символьного устройства (register_chrdev()). Но эта техника потеряла актуальности, и используются на сегодня — это и будет наш третий альтернативный способ создания устройства. Но, помимо этого, пользуясь тем, что способ регистрации устройства никоим образом не связан с реализующими операции функциями, мы дополним схему нашего устройства обработчиком управляющих операций ioctl(), что и есть главной целью нашего следующего примера:

hello_dev.c :

	#include "ioctl.h" 
	#include "../dev.h" 

	// Работа с символьным устройством в старом стиле... 
	static int hello_open( struct inode *n, struct file *f ) { 
	   // ... при этом MINOR номер устройства должна обслуживать функция open: 
	   // unsigned int minor = iminor( n ); 
	   return 0; 
	} 

	static int hello_release( struct inode *n, struct file *f ) { 
	   return 0; 
	} 

	static int hello_ioctl( struct inode *n, struct file *f, 
	                        unsigned int cmd, unsigned long arg ) { 
	   if( ( _IOC_TYPE( cmd ) != IOC_MAGIC ) ) return -ENOTTY; 
	   switch( cmd ) { 
	      case IOCTL_GET_STRING: 
	         if( copy_to_user( (void*)arg, hello_str, _IOC_SIZE( cmd ) ) ) return -EFAULT; 
	         break; 
	      default: 
	         return -ENOTTY; 
	   } 
	   return 0; 
	} 

	static const struct file_operations hello_fops = { 
	   .owner = THIS_MODULE, 
	   .open = hello_open, 
	   .release = hello_release, 
	   .read  = hello_read, 
	   .ioctl = hello_ioctl 
	}; 

	#define HELLO_MAJOR 200 
	#define HELLO_MODNAME "hello_dev"
	static int __init hello_init( void ) { 
	   int ret = register_chrdev( HELLO_MAJOR, HELLO_MODNAME, &hello_fops ); 
	   if( ret < 0 ) { 
	      printk( KERN_ERR "Can not register char device\n" ); 
	      goto err; 
	   } 
	err: 
	   return ret; 
	} 

	static void __exit hello_exit( void ) { 
	  unregister_chrdev( HELLO_MAJOR, HELLO_MODNAME ); 
	} 

Заголовочный файл, совместно используемый и модулем, и работающим с ним пользовательским процессом, служащий для их согласованного использования типов и констант:

ioctl.h :

	typedef struct _RETURN_STRING { 
	   char buf[ 160 ]; 
	} RETURN_STRING; 
	
	#define IOC_MAGIC    'h' 
	#define IOCTL_GET_STRING _IOR( IOC_MAGIC, 1, RETURN_STRING ) 

Пользовательский (тестовый) процесс, пользующийся вызовами ioctl():

ioctl.c :

	#include <fcntl.h>
	#include <stdio.h>
	#include <sys/ioctl.h>
	#include <stdlib.h>
	#include "ioctl.h"

	#define ERR(...) fprintf( stderr, "\7" __VA_ARGS__ ), exit( EXIT_FAILURE )

	int main( int argc, char *argv[] ) {
	   int dfd;                  // дескриптор устройства
	   if( ( dfd = open( "/dev/hello", O_RDWR ) ) < 0 ) ERR( "Open device error: %m\n" );
	   RETURN_STRING buf;
	   if( ioctl( dfd, IOCTL_GET_STRING, &buf ) ) ERR( "IOCTL_GET_STRING error: %m\n" );
	   fprintf( stdout, (char*)&buf );
	   close( dfd );
	   return EXIT_SUCCESS;
	};

Makefile :

	CURRENT = $(shell uname -r)
	KDIR = /lib/modules/$(CURRENT)/build
	PWD = $(shell pwd)
	DEST = /lib/modules/$(CURRENT)/misc

	TARGET = hello_dev
	obj-m      := $(TARGET).o

	all: default ioctl

	default:
	        $(MAKE) -C $(KDIR) M=$(PWD) modules

	ioctl:  ioctl.h ioctl.c
	        gcc ioctl.c -o ioctl

Испытываем полученное изделие:

$ sudo mknod -m0666 /dev/hello c 200 0

$ ls -l /dev | grep 200

crw-rw-rw- 1 root root 200, 0 Июн 19 00:55 hello

$ cat /dev/hello

cat: /dev/hello: Нет такого устройства или адреса

$ sudo insmod ./hello_dev.ko

$ echo $?

0

$ cat /dev/hello

Hello, world!

$ cat /proc/devices | grep hel

200 hello_dev

$ ./ioctl

Hello, world!

$ sudo rmmod hello_dev

$ ./ioctl

Open device error: No such device or address

$ cat /dev/hello

cat: /dev/hello: Нет такого устройства или адреса

$ ls -l /dev | grep 200

crw-rw-rw- 1 root root 200, 0 Июн 19 00:55 hello

$ cat /proc/devices | grep hel

$


Предыдущий раздел: Оглавление Следующий раздел:
Драйверы: примеры реализации   Множественное открытие устройства