Il kernel di Linux Riferimenti: – guntis/unix/kernel_modules.ppt (Dzintars Lepešs, University of...

35
Il kernel di Linux Riferimenti: http://www.ltn.lv/~guntis/unix/kernel_modules. ppt (Dzintars Lepešs, University of Latvia) – http://freeelectrons.com

Transcript of Il kernel di Linux Riferimenti: – guntis/unix/kernel_modules.ppt (Dzintars Lepešs, University of...

Page 1: Il kernel di Linux Riferimenti: – guntis/unix/kernel_modules.ppt (Dzintars Lepešs, University of Latvia)guntis/unix/kernel_modules.ppt.

Il kernel di Linux

Riferimenti:– http://www.ltn.lv/~guntis/unix/kernel_modules.ppt (Dzintars Lepešs, University of Latvia)

– http://freeelectrons.com

Page 2: Il kernel di Linux Riferimenti: – guntis/unix/kernel_modules.ppt (Dzintars Lepešs, University of Latvia)guntis/unix/kernel_modules.ppt.

Struttura dei sorgenti

• arch Codice dipendente dall'architettura• documentation Documentazione del kernel;• drivers Tutti i device drivers • fs Filesystems• include File header del kernel• kernel Scheduler, …• lib Librerie

• …

• Makefile Makefile principale

Page 3: Il kernel di Linux Riferimenti: – guntis/unix/kernel_modules.ppt (Dzintars Lepešs, University of Latvia)guntis/unix/kernel_modules.ppt.

Compilazione

Configurazione kernel:– make xconfig– oppure make menuconfig– oppure make oldconfig

Generano il file .config con le impostazioni scelte.

Compilazione:

make [opzioni]

Page 4: Il kernel di Linux Riferimenti: – guntis/unix/kernel_modules.ppt (Dzintars Lepešs, University of Latvia)guntis/unix/kernel_modules.ppt.

Compilazione• make bzImage

– crea il kernel compilato

• make modules– compila i moduli

• make modules_install– installa i moduli

• make … -j 4– compilazione parallela

• make mrproper– cancellazione file intermedi

Page 5: Il kernel di Linux Riferimenti: – guntis/unix/kernel_modules.ppt (Dzintars Lepešs, University of Latvia)guntis/unix/kernel_modules.ppt.

Implementazione• Vengono memorizzati come file oggetto in formato ELF;

• Viene memorizzato l’indirizzo di tutti i simboli esportati

(/proc/syms <2.6 /proc/kallsyms - 2.6);

• Viene momorizzato l’uso e le dipendenze dei moduli usati

(/proc/modules), caricati con insmod o modprobe.

• Per ogni modulo vengono mantenuti:

– Una struttura dati con le informazioni su di esso;

– Una stringa identificativa;

– L’implementazione.

Page 6: Il kernel di Linux Riferimenti: – guntis/unix/kernel_modules.ppt (Dzintars Lepešs, University of Latvia)guntis/unix/kernel_modules.ppt.

Module Object

Page 7: Il kernel di Linux Riferimenti: – guntis/unix/kernel_modules.ppt (Dzintars Lepešs, University of Latvia)guntis/unix/kernel_modules.ppt.

Linking e Unlinking di moduli

Page 8: Il kernel di Linux Riferimenti: – guntis/unix/kernel_modules.ppt (Dzintars Lepešs, University of Latvia)guntis/unix/kernel_modules.ppt.

Programs for linking and unlinking

• insmod– Reads from the name of the module to be linked– Locates the file containing the module's object code– Computes the size of the memory area needed to store the module

code, its name, and the module object– Invokes the create_module( ) system call– Invokes the query_module( ) system call– Using the kernel symbol table, the module symbol tables, and the

address returned by the create_module( ) system call, relocates the object code included in the module's file.

– Allocates a memory area in the User Mode address space and loads with a copy of the module object

– Invokes the init_module( ) system call, passing to it the address of the User Mode memory area

– Releases the User Mode memory area and terminates

Page 9: Il kernel di Linux Riferimenti: – guntis/unix/kernel_modules.ppt (Dzintars Lepešs, University of Latvia)guntis/unix/kernel_modules.ppt.

Programs for linking and unlinking

• lsmod

reads /proc/modules

• rmmod– From reads the name of the module to be unlinked.– Invokes the query_module( )– Invokes the delete_module( ) system call, with the QM_REFS

subcommand several times, to retrieve dependency information on the linked modules.

• modprobetakes care of possible complications due to module dependencies,

uses depmod program and /etc/modules.conf file

Page 10: Il kernel di Linux Riferimenti: – guntis/unix/kernel_modules.ppt (Dzintars Lepešs, University of Latvia)guntis/unix/kernel_modules.ppt.

Device drivers• There are two major ways

for a kernel module to talk to processes:

• To use the proc file system (/proc directory)

• Through device files (/dev directory)

• Device driver sits between some hardware and the kernel I/O subsystem. Its purpose is to give the kernel a consistent interface to the type of hardware it "drives".

Page 11: Il kernel di Linux Riferimenti: – guntis/unix/kernel_modules.ppt (Dzintars Lepešs, University of Latvia)guntis/unix/kernel_modules.ppt.

Driver a caratteri

Accesso tramite flusso sequenziale di caratteri singoli

Individuabili per il loro tipo di file c (ls -l):

crwrw1 root uucp 4, 64 Feb 23 2004 /dev/ttyS0crww1 jdoe tty 136, 1 Sep 13 06:51 /dev/pts/1crw1 root root 13, 32 Feb 23 2004 /dev/input/mouse0crwrwrw1 root root 1, 3 Feb 23 2004 /dev/null

Esempio: tastiera, mouse, porta parallela, IrDA, porta Bluetooth, console, terminale...

Page 12: Il kernel di Linux Riferimenti: – guntis/unix/kernel_modules.ppt (Dzintars Lepešs, University of Latvia)guntis/unix/kernel_modules.ppt.

Driver a blocchi

Accesso casuale a blocchi di dati di dimensioni fisse.

Individuabili per il loro tipo di file b (ls l):

brwrw1 root disk 3, 1 Feb 23 2004 /dev/hda1

Esempi: hard disk e floppy disk, ram disk, dispositivi loop...

Page 13: Il kernel di Linux Riferimenti: – guntis/unix/kernel_modules.ppt (Dzintars Lepešs, University of Latvia)guntis/unix/kernel_modules.ppt.

Numeri di device

Ogni device ha due numeri associati:

• major number– Associato ad ogni driver in maniera unica

• minor number– Associato ad ogni device in maniera unica

Page 14: Il kernel di Linux Riferimenti: – guntis/unix/kernel_modules.ppt (Dzintars Lepešs, University of Latvia)guntis/unix/kernel_modules.ppt.

Creazione dei file di device

I file di device non vengono creati al momento di caricare il driver, devono essere creati esplicitamente:

mknod /dev/<device> [c|b] <major> <minor>

Esempi:• mknod /dev/ttyS0 c 4 64• mknod /dev/hda1 b 3 1

Page 15: Il kernel di Linux Riferimenti: – guntis/unix/kernel_modules.ppt (Dzintars Lepešs, University of Latvia)guntis/unix/kernel_modules.ppt.

Modulo minimale/* hello.c */#include <linux/init.h>#include <linux/module.h>#include <linux/kernel.h>static int hello_init(void){

printk(KERN_ALERT “inizio\n");return 0;

}

static void hello_exit(void){

printk(KERN_ALERT “fine\n");}

module_init(hello_init);module_exit(hello_exit);MODULE_LICENSE("GPL");

Page 16: Il kernel di Linux Riferimenti: – guntis/unix/kernel_modules.ppt (Dzintars Lepešs, University of Latvia)guntis/unix/kernel_modules.ppt.

Funzioni di libreria

• Non si possono usare le funzioni della libreria standard C come printf(), strcat(), ...

• Linux fornisce alcune funzioni, come ad esempio printk(), la cui interfaccia e molto simile a quella di printf().

• Si possono usare solo gli header del kernel!

Page 17: Il kernel di Linux Riferimenti: – guntis/unix/kernel_modules.ppt (Dzintars Lepešs, University of Latvia)guntis/unix/kernel_modules.ppt.

Compilazione di un kernel module

• A kernel module is not an independent executable, but an object file which will be linked into the kernel in runtime and they should be compiled with

– -c flag– _KERNEL_ symbol– MODULE symbol– LINUX symbol– CONFIG_MODVERSIONS symbol

Page 18: Il kernel di Linux Riferimenti: – guntis/unix/kernel_modules.ppt (Dzintars Lepešs, University of Latvia)guntis/unix/kernel_modules.ppt.

Example of simple char device/* The necessary header files *//* Standard in kernel modules */#include <linux/kernel.h> /* We’re doing kernel work */#include <linux/module.h> /* Specifically, a module */#if CONFIG_MODVERSIONS==1 #define MODVERSIONS #include <linux/modversions.h>#endif#include <linux/fs.h>#include <linux/wrapper.h>

#ifndef KERNEL_VERSION #define KERNEL_VERSION(a,b,c) ((a)*65536+(b)*256+(c))#endif

#include <asm/uaccess.h>

#define SUCCESS 0/* Device Declarations *//* The name for our device, as it will appear/* in /proc/devices */#define DEVICE_NAME "char_dev"#define BUF_LEN 80

Page 19: Il kernel di Linux Riferimenti: – guntis/unix/kernel_modules.ppt (Dzintars Lepešs, University of Latvia)guntis/unix/kernel_modules.ppt.

/* Used to prevent *//* concurent access into the same device */static int Device_Open = 0;/* The message the device will give when asked */static char Message[BUF_LEN];static char *Message_Ptr;

/* This function is called whenever a process* attempts to open the device file */static int device_open(struct inode *inode, struct file *file){ static int counter = 0; #ifdef DEBUG printk ("device_open(%p,%p)\n", inode, file); #endif printk("Device: %d.%d\n“, inode->i_rdev >> 8, inode->i_rdev & 0xFF); if (Device_Open) return -EBUSY; Device_Open++; sprintf(Message, counter++, Message_Ptr = Message; MOD_INC_USE_COUNT; return SUCCESS;}

Page 20: Il kernel di Linux Riferimenti: – guntis/unix/kernel_modules.ppt (Dzintars Lepešs, University of Latvia)guntis/unix/kernel_modules.ppt.

if (Device_Open) return -EBUSY; Device_Open++; sprintf(Message, counter++, Message_Ptr = Message; MOD_INC_USE_COUNT; return SUCCESS;}

static int device_release(struct inode *inode, struct file *file){ Device_Open --; MOD_DEC_USE_COUNT; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) return 0; #endif}

Page 21: Il kernel di Linux Riferimenti: – guntis/unix/kernel_modules.ppt (Dzintars Lepešs, University of Latvia)guntis/unix/kernel_modules.ppt.

static ssize_t device_read(struct file *file, char *buffer, /* The buffer to fill with data */ size_t length, /* The length of the buffer */ loff_t *offset) /* Our offset in the file */{ /* Number of bytes actually written to the buffer */ int bytes_read = 0; /* If we’re at the end of the message, return 0 if (*Message_Ptr == 0) return 0; /* Actually put the data into the buffer */ while (length && *Message_Ptr) { put_user(*(Message_Ptr++), buffer++); length --; bytes_read ++; }

#ifdef DEBUG printk ("Read %d bytes, %d left\n", bytes_read, length);#endif return bytes_read;}

Page 22: Il kernel di Linux Riferimenti: – guntis/unix/kernel_modules.ppt (Dzintars Lepešs, University of Latvia)guntis/unix/kernel_modules.ppt.

static ssize_t device_write(struct file *file, const char *buffer, /* The buffer */ size_t length, /* The length of the buffer */ loff_t *offset) /* Our offset in the file */{ return -EINVAL;}

Page 23: Il kernel di Linux Riferimenti: – guntis/unix/kernel_modules.ppt (Dzintars Lepešs, University of Latvia)guntis/unix/kernel_modules.ppt.

/* Module Declarations */struct file_operations Fops = { NULL, /* seek */ device_read, device_write, NULL, /* readdir */ NULL, /* select */ NULL, /* ioctl */ NULL, /* mmap */ device_open,#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) NULL, /* flush */#endif device_release /* a.k.a. close */};

Page 24: Il kernel di Linux Riferimenti: – guntis/unix/kernel_modules.ppt (Dzintars Lepešs, University of Latvia)guntis/unix/kernel_modules.ppt.

/* Initialize the module - Register the character device */int init_module(){ /* Register the character device */ Major = module_register_chrdev(0, DEVICE_NAME, &Fops);

/* Negative values signify an error */ if (Major < 0) { printk ("%s device failed with %d\n", "Sorry, registering the character", Major); return Major; } return 0;}

/* Cleanup - unregister the appropriate file from /proc */void cleanup_module(){ int ret; /* Unregister the device */ ret = module_unregister_chrdev(Major, DEVICE_NAME); if (ret < 0) printk("Error in unregister_chrdev: %d\n", ret);}

Page 25: Il kernel di Linux Riferimenti: – guntis/unix/kernel_modules.ppt (Dzintars Lepešs, University of Latvia)guntis/unix/kernel_modules.ppt.

Internal components of the NT-based operating system

Page 26: Il kernel di Linux Riferimenti: – guntis/unix/kernel_modules.ppt (Dzintars Lepešs, University of Latvia)guntis/unix/kernel_modules.ppt.

Types of Kernel-Mode Drivers

Page 27: Il kernel di Linux Riferimenti: – guntis/unix/kernel_modules.ppt (Dzintars Lepešs, University of Latvia)guntis/unix/kernel_modules.ppt.

Current Driver Models• Windows has several different driver models

– Windows Driver Model (WDM) is the generic model

– Specific driver models for popular devices classes• Storage, Networking, Printing, Imaging, etc...

• Some built on top of WDM. Others run as user-mode services.

• WDM Features– Asynchronous, packet-based I/O

– I/O Cancellation

– Layering of drivers

– Dynamic loading and unloading of drivers

– Plug and Play & Power management

– Low-level high-performance interfaces

Page 28: Il kernel di Linux Riferimenti: – guntis/unix/kernel_modules.ppt (Dzintars Lepešs, University of Latvia)guntis/unix/kernel_modules.ppt.

Limitations with Current Models• Generic driver model (WDM) is too complex

– Focuses on very advanced drivers which punishes simple ones

• Many drivers must be written in kernel mode – Even though much functionality could be user mode

• Developers spend too much time driving our software– Cannot concentrate on driving their hardware

– Driver quality suffers as a result

• Do not allow extension and future growth

Page 29: Il kernel di Linux Riferimenti: – guntis/unix/kernel_modules.ppt (Dzintars Lepešs, University of Latvia)guntis/unix/kernel_modules.ppt.

Overview of Current Driver Models

Device/Driver Classes Current Model

Display Adapters Video port

Storage Adapters (SCSI & ATA) SCSIport, Storport, ATAport,

Network Adapters NDIS

Video Capture AvStream

Audio Adapters AVStream, PortCls

File System filters FS Mini filter

Printers UniDrv

Scanners,Cameras WIA

PCI, PC Card, generic filter drivers WDM

Modems, Cable Modem WDM & NDIS WDM

Biometric Devices WDM

Smart Card Devices WDM

Keyboard/Mouse Filters WDM

Legacy Devices (Serial, Parallel) WDM

Portable Media Players WMDM

UPnP & Network Connected Devices, Cell Phones

No support

USB, 1394, Bluetooth, SD devices WDM (kernel), no support (user)

Others WDM

Page 30: Il kernel di Linux Riferimenti: – guntis/unix/kernel_modules.ppt (Dzintars Lepešs, University of Latvia)guntis/unix/kernel_modules.ppt.

Kernel-Mode or User-Mode Driver?

You must use kernel mode when you:• Need direct hardware access, for example,

– Require DMA– Must handle interrupts– Need access to device registers

• Have strict timing requirements– UMDF will have increased latency

• Need kernel-only resources– Or kernel components need access to your driver

Page 31: Il kernel di Linux Riferimenti: – guntis/unix/kernel_modules.ppt (Dzintars Lepešs, University of Latvia)guntis/unix/kernel_modules.ppt.

Introduction to WDM

To allow driver developers to write device drivers that are source-code compatible across all Microsoft Windows operating systems, the Windows Driver Model (WDM) was introduced. Kernel-mode drivers that follow WDM rules are called WDM drivers. All WDM drivers must:

Include wdm.h, not ntddk.h. (Note that wdm.h is a subset of ntddk.h.)

• Be designed as a bus driver, a function driver, or a filter driver.

• Create device objects. • Support Plug and Play. • Support power management. • Support Windows Management Instrumentation (WMI)

Page 32: Il kernel di Linux Riferimenti: – guntis/unix/kernel_modules.ppt (Dzintars Lepešs, University of Latvia)guntis/unix/kernel_modules.ppt.

EsempioNTSTATUSDriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath{

UNREFERENCED_PARAMETER (RegistryPath);

DebugPrint (("Entered Driver Entry\n")); DriverObject->MajorFunction[IRP_MJ_CREATE] = GpdDispatch; DriverObject->MajorFunction[IRP_MJ_CLOSE] = GpdDispatch; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = GpdDispatch; DriverObject->DriverUnload = GpdUnload; DriverObject->MajorFunction[IRP_MJ_PNP] = GpdDispatchPnp; DriverObject->MajorFunction[IRP_MJ_POWER] = GpdDispatchPower; DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = GpdDispatchSystemControl; DriverObject->DriverExtension->AddDevice = GpdAddDevice;

return STATUS_SUCCESS;}

Page 33: Il kernel di Linux Riferimenti: – guntis/unix/kernel_modules.ppt (Dzintars Lepešs, University of Latvia)guntis/unix/kernel_modules.ppt.

EsempioNTSTATUS GpdAddDevice(/* Plug & Play */ IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject )

{ NTSTATUS status = STATUS_SUCCESS; PDEVICE_OBJECT deviceObject = NULL; PLOCAL_DEVICE_INFO deviceInfo; UNICODE_STRING ntDeviceName; UNICODE_STRING win32DeviceName;

PAGED_CODE();

DebugPrint(("Entered AddDevice: %p\n", PhysicalDeviceObject));

RtlInitUnicodeString(&ntDeviceName, GPD_DEVICE_NAME);

status = IoCreateDevice(DriverObject, sizeof (LOCAL_DEVICE_INFO), &ntDeviceName, GPD_TYPE, FILE_DEVICE_SECURE_OPEN, // do security checks on relative open FALSE, &deviceObject);

Page 34: Il kernel di Linux Riferimenti: – guntis/unix/kernel_modules.ppt (Dzintars Lepešs, University of Latvia)guntis/unix/kernel_modules.ppt.

Esempioif (!NT_SUCCESS (status)) { DebugPrint(("IoCreateDevice failed: %x\n", status)); return status; }

RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME);

status = IoCreateSymbolicLink( &win32DeviceName, &ntDeviceName );

if (!NT_SUCCESS(status)) // If we we couldn't create the link then { // abort installation. IoDeleteDevice(deviceObject); return status; }

deviceInfo = (PLOCAL_DEVICE_INFO) deviceObject->DeviceExtension; deviceInfo->NextLowerDriver = IoAttachDeviceToDeviceStack ( deviceObject, PhysicalDeviceObject); if(NULL == deviceInfo->NextLowerDriver) { IoDeleteSymbolicLink(&win32DeviceName); IoDeleteDevice(deviceObject); return STATUS_NO_SUCH_DEVICE; }

Page 35: Il kernel di Linux Riferimenti: – guntis/unix/kernel_modules.ppt (Dzintars Lepešs, University of Latvia)guntis/unix/kernel_modules.ppt.

EsempioIoInitializeRemoveLock (&deviceInfo->RemoveLock , PORTIO_TAG, 1, // MaxLockedMinutes 5); // HighWatermark, this parameter is // used only on checked build. deviceObject->Flags |= DO_POWER_PAGABLE;

deviceInfo->DeviceObject = deviceObject;

INITIALIZE_PNP_STATE(deviceInfo);

deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

deviceInfo->PortMemoryType = 1;

DebugPrint(("AddDevice: %p to %p->%p \n", deviceObject, deviceInfo->NextLowerDriver, PhysicalDeviceObject));

return STATUS_SUCCESS;

}