/*
Bu belgenin telif haklar� Necati Ersen ���EC�'ye aittir.
K�k: http://acikkod.org
�lk bask�: 2004-04-22
Son de�i�iklik: 2004-04-22
Bu d�k�man A��kkod.ORG Belge Yaz�m ve Da��t�m Lisans� ile da��t�lmaktad�r.
*/
/dev/null Ayg�t� ve S�r�c� Programlama
Bu bolumde, /dev/null ayg�t�n�n s�r�c�s�n�n nas�l yaz�ld���n� inceleyece�iz.
Linux �ekirde�inde her ayg�t i�in yap�lmas� gereken belli ba�l� i�lemler vard�r.
Okuma (read), yazma(write), a�ma (open) gibi.
Linux'de bir sistem �a�r�s� olu�tu�u zaman (�rne�in open), hangi ayg�t i�in
olu�turtu ise, o ayg�t�n ilgili fonksiyonu �al��t�r�l�r.
Bu i�lemler, Linux �ekirde�inde karakter ayg�tlar� i�in file_operations isimli
bir yap�da tutulur. linux/fs.h ta tan�mlanan file_operations yap�s� a�a��daki
gibidir.
struct file_operations {
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char *, size_t, loff_t *);
int (*readdir) (struct file *, void *, filldir_t);
unsigned int (*poll) (struct file *, struct poll_table_struct *);
int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
int (*mmap) (struct file *, struct vm_area_struct *);
int (*open) (struct inode *, struct file *);
int (*flush) (struct file *);
int (*release) (struct inode *, struct file *);
int (*fsync) (struct file *, struct dentry *);
int (*fasync) (int, struct file *, int);
int (*check_media_change) (kdev_t dev);
int (*revalidate) (kdev_t dev);
int (*lock) (struct file *, int, struct file_lock *);
} ;
Biz bunlardan sadece gerekenleri kullanaca��z.
Bu yap�n�n amac�, sistem bu ayg�t ile ilgili olu�an sistem �a�r�lar�n� yerine
getirirken hangi fonksiyonlar� kullanaca��n� belirtmektir.
Hangi fonksiyonlar� kullanaca��m�z� belirledikten sonra kullanaca��m�z ayg�t�
se�meliyiz. Bu ayg�t�n bir major ve minor numaras� olmas� gerekti�ini biliyoruz.
Yapmam�z gerek �ey, sisteme bu ayg�t i�in yap�lan sistem �a�r�lar�nda kullan�lacak
fonksiyonlar�n tutuldu�u, tan�mlad���m�z file_operations yap�s�n� kullanmas�
gerekti�ini belirtmek. Bu i�lemi init_module() fonksiyonu i�inde yapmam�z gerekiyor.
Sisteme bir karakter ayg�t eklemek istedi�imizde;
int register_chrdev(unsigned int, const char *, struct file_operations *)
�eklinde tan�mlanan register_chrdev() fonksiyonunu kullan�yoruz. Burada birinci
parametre, ayg�t�n major numaras�, ikinci parametre ayg�t�n ismi, ���nc�s� ise
tan�mlad���m�z file_operations yap�s�na pointerdir.
i = register_chrdev (201, "bdevice", &fops);
register_chrdev() fonksiyonunu major numaras� olarak 0 verirsek, sistem otomatik
olarak ayg�ta bir major numaras� verecek ve fonksiyonun geri d�n�� de�eri ayg�t
i�in kullan�lacak olan major numaras� olacakt�r.
register_chrdev() fonksiyonu ikinci parametre ile belirtti�imiz ayg�t olup olmad���n�
kontrol etmez. Bu y�zden i�lem ba�ar�l� ise verdi�imiz parametreye g�re 0 yada major
numaras� ile geri d�necektir.
int init_module (void)
{
int i = 0;
i = register_chrdev (device_major_number, DEVICE_NAME , &fops);
if (i < 0) return i;
if (device_major_number == 0) device_major_number = i;
return 0;
}
��lerimiz bitti ve mod�l� bellekten ataca��z. Bu durumda yap�lmas� gereken �ey
cleanup_module() fonksiyonu ile kulland���m�z ayg�t� unregister etmek.
int unregister_chrdev(unsigned int major, const char * name);
unregister_chrdev() fonksiyonundaki ilk parametre ayg�t�n major numaras�, ikincisi
ise ayg�t�n ismidir.
void cleanup_module (void)
{
unregister_chrdev (201, "bdevice");
}
/dev/null ayg�t� ad�ndan da anla��ld��� gibi hi� bir �ey yapmayan, herhangi bir
bellek blogu kullanmayan okuma ve yazma i�lemleri yap�labilen bir ayg�tt�r. Yazmak
istedi�imizde yazmak istedi�imiz t�m data n�n yaz�ld���n�, okumak istedi�imizde
ise 0 dondurur.
siseci:~/kernel# cat /dev/null
siseci:~/kernel# cat /etc/passwd > /dev/null
siseci:~/kernel# cat /dev/null
siseci:~/kernel#
Ayg�t�m�z bir karakter ayg�t oldu�u i�in open ve close sistem �a�r�lar�n� yan�tlayacak
fonksiyonlara ihtiyac�m�z olmayacak.
read ve write i�lemleri i�in iki fonksiyon yazmam�z gerekecek.
Sistemde �al��an null ayg�t� var oldu�u i�in ayg�t�n ad�n� null2 olarak kullanal�m.
/dev/null2 ayg�t�m�z i�in read system ca�r�s� olu�tu�unda bu �a�r�y�
null2_read() fonksiyonu ile cevaplayal�m. read i�lemi sonucunda kullan�c�ya
dosya sonunda gelindi yada okunacak bilgi yok anlam�na gelen 0 d�ndermemiz
gerekiyor.
read() fonksiyonunun nas�l kullan�ld���n� zaten file_operations yap�s�ndan biliyoruz.
static ssize_t
null2_read (struct file * file, char * buf, size_t count, loff_t *ppos)
{
return 0;
}
write i�lemi i�in ise, kullan�c� ka� bayt yazmak istediyse, o kadar bilginin yaz�ld���n�
do�rulamak i�in, kullan�c�n�n bize parametre olarak verdi�i uzunlu�u, kullan�c�ya geri
d�ndermemiz yeterli olacakt�r. Fonksiyonumuz null2_write() olsun.
static ssize_t
null2_write (struct file * file, const char * buf, size_t size, loff_t * ppos)
{
return size;
}
file_operations yap�m�za bakt���m�zda,
static struct file_operations null2_fops = {
NULL, /* lseek */
null2_read, /* read */
null2_write, /* write */
NULL, /* readdir */
NULL, /* select */
NULL, /* ioctl */
NULL, /* mmap */
NULL, /* open */
NULL, /* release */
NULL, /* fsync */
} ;
�eklinde olacakt�r.
T�m koda bakacak olursak;
#ifndef __KERNEL__
#define __KERNEL__
#define MODULE
#define LINUX
#endif
#include <linux/module.h>
#include <linux/version.h>
#include <linux/fs.h>
static ssize_t null2_read (struct file *, char * , size_t, loff_t *);
static ssize_t null2_write (struct file *, const char *, size_t, loff_t *);
static struct file_operations null2_fops = {
read: null2_read,
write: null2_write,
};
static ssize_t
null2_read (struct file * file, char * buf, size_t count, loff_t *ppos)
{
return 0;
}
static ssize_t
null2_write (struct file * file, const char * buf, size_t size, loff_t * ppos)
{
return size;
}
int init_module (void)
{
int i = 0;
i = register_chrdev (222, "null2", & null2_fops);
if (i < 0) return i;
return 0;
}
void cleanup_module (void)
{
unregister_chrdev (222, "null2");
}
Derleyip sisteme y�kleyelim.
siseci:~/kernel# mknod /dev/null2 c 222 0
siseci:~/kernel# gcc -Wall -c null2.c
siseci:~/kernel# ls -al null2.o
-rw------- 1 root root 1468 Jan 1 03:07 null2.o
siseci:~/kernel# insmod null2
siseci:~/kernel# echo Deneme > /dev/null2
siseci:~/kernel# cat /dev/null2
siseci:~/kernel# ls -al /dev/null2
crw------- 1 root root 222, 0 Jan 1 1998 /dev/null2
siseci:~/kernel# rmmod null2
B�ylece sisteme y�klemi� ve testini de yapm�� olduk. Yukardaki testlerden de anla��ld���
�zere null2 ayg�t�, sistemdeki null ayg�t� gibi davranmaktad�r.
Linux �ekirdek kodlar�na bakt���m�zda null (linux/drivers/char/mem.c ) ayg�t�n�n,
lseek() sistem �a�r�s� i�in de bir fonksiyon yaz�lm��. Bu dosyaya g�z atman�z� tavsiye
ederim.
Necati Ersen ���EC�
25 �ubat 2004