This document provides information about synchronization primitives like spinlocks, semaphores, and waitqueues in Linux and Windows kernel programming. It lists functions for initializing, acquiring, and releasing locks. It also discusses list data structures and functions for managing lists. Common tools for kernel development and debugging on each platform are listed.
This document provides information about synchronization primitives like spinlocks, semaphores, and waitqueues in Linux and Windows kernel programming. It lists functions for initializing, acquiring, and releasing locks. It also discusses list data structures and functions for managing lists. Common tools for kernel development and debugging on each platform are listed.
Windows int atomic_dec_and_test(atomic_t *v); Compilarea nucleului PVOID ExAllocatePoolWithTag( Windows IN POOL_TYPE PoolType, KSPIN_LOCK – tip spinlock make menuconfig – configurarea nucleului Linux IN SIZE_T NumberOfBytes, VOID KeInitializeSpinLock( make – compilarea nucleului Linux IN ULONG Tag); – alocare memorie IN PKSPIN_LOCK SpinLock); – init, ializare spinlock make modules_install – instalează modulele VOID ExFreePoolWithTag( VOID KeAcquireSpinLock( make install – instalează imagina de kernel IN PVOID P, IN PKSPIN_LOCK SpinLock, build – compilarea nucleului Windows IN ULONG Tag); – eliberare memorie OUT PKIRQL OldIrql); – obt, inere lock /boot/grub/menu.lst – fis, ierul de configurare a GRUB VOID KeReleaseSpinLock( C:\boot.ini – configurare booting pe Windows IN PKSPIN_LOCK SpinLock, Liste IN KIRQL NewIrql); – eliberare lock KESEMAPHORE – tip semafor Aplicat, ii utile ı̂n kernel programming Linux VOID KeInitializeSemaphore( struct list_head – listă IN PRKSEMAPHORE Semaphore, GCC, GNU Make, GDB – suita standard pe Linux list_add(struct list_head *new, struct list_head *head) IN LONG Count, Windows Driver Kit (WDK) – suita de driver development pe – inserează new după head IN LONG Limit); – init, ializare semafor Windows list_del(struct list_head *entry) NSTATUS KeWaitForSingleObject(...) – decrementare semafor Windows Research Kernel (WRK) – o parte din sursele nucleului – s, terge un element din listă LONG KeReleaseSemaphore(...) – incrementare semafor Windows list_empty(struct list_head *head) InterlockedCompareExchange(...) WinDbg, LiveKd – utilitare de debugging ı̂n Windows – verifică dacă o listă este goală InterlockedDecrement(...) Linux Cross Reference (LXR) – interfat, ă web pentru source list_entry(ptr, type, member) InterlockedExchange(...) browsing – ı̂ntoarce structura ce cont, ine list head-ul InterlockedExchangeAdd(...) list_for_each(pos, head) InterlockedIncrement(...) – parcurge o listă Crearea unui modul simplu ı̂n Linux list_for_each_safe(pos, head) kernel.h, init.h, module.h – headere necesare – parcurge o listă (safe pentru s, tergerea unui element) Device drivere ı̂n Linux MODULE_[DESCRIPTION|AUTHOR|LICENSE] – informat, ii modul Windows static int init_func(void) – entry point SINGLE_LIST_ENTRY – listă mknod <fis, ier> <c/b> <major> <minor> static void exit_func(void) – exit point LIST_ENTRY – listă dublu ı̂nlănt, uită int register_chrdev_region(dev_t first, unsigned int count, module_init, module_exit – specificare funct, ii entry / exit point VOID PushEntryList( char *name) IN PSINGLE_LIST_ENTRY ListHead void unregister_chrdev_region(dev_t first, unsigned int IN PSINGLE_LIST_ENTRY Entry); count) Crearea unui modul simplu ı̂n Windows – inserează Entry void cdev_init(struct cdev *cdev, struct file_operations VOID PopEntryList( *fops) ntddk.h – header necesar IN PSINGLE_LIST_ENTRY ListHead); int cdev_add(struct cdev *dev, dev_t num, unsigned int NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING – s, terge primul element din listă count) registry) – entry point void cdev_del(struct cdev *dev) driver->DriverUnload – ı̂nregistrare exit point int (*open) (struct inode *, struct file *) Locking ssize_t (*read) (struct file *, char __user *, size_t, Toolchains Linux loff_t *); ssize_t (*write) (struct file *, const char __user *, spinlock_t – tip spinlock make, kbuild – compilare module Linux size_t, loff_t *); spin_lock_init(spinlock_t *lock); – init, ializare spinlock lsmod, insmod, rmmod – lucrul cu module ı̂n Linux int (*ioctl) (struct inode *, struct file *, unsigned int, spin_lock(spinlock_t *lock); – obt, inere lock printk, addr2line, objdump, netconsole – debugging Linux unsigned long); spin_unlock(spinlock_t *lock); – eliberare lock nmake, sources – compilare module Windows int (*release) (struct inode *, struct file *); struct semaphore – tip semafor driver [list, load, unload] – lucrul cu module ı̂n Windows void sema_init(struct semaphore *sem, int val); WinDbg, !analyze -v – debugging Windows – init, ializare semafor la valoarea val Cozi de as, teptare – waitqueues void down(struct semaphore *sem); – decrementare semafor Alocare memorie void up(struct semaphore *sem); – incrementare semafor DECLARE_WAIT_QUEUE_HEAD(wait queue_head_t *q); atomic_t – tip atomic void init_waitqueue_head(wait_queue_head_t *q); Linux atomic_set(atomic_t *v, int i) int wait_event(wait_queue_head_t *q, int condition); void *kmalloc(size_t size, int flags); – alocare memorie int atomic_read(atomic_t *v); int wait_event_interruptible(wait_queue_head_t *q, int void *kzalloc(size_t size, int flags); – alocare memorie void atomic_add(int i, atomic_t *v); condition); init, ializată la zero void atomic_sub(int i, atomic_t *v); int wait_event_timeout(wait_queue_head_t *q, int condition, void kfree(const void *mem); – eliberare memorie void atomic_inc(atomic_t *v); int timeout); int wait_event_interruptible_timeout(wait_queue_head_t *q, VOID ProbeForRead/ProbeForWrite( IN ULONG BusNumber, int condition, int timeout); CONST VOID *Address, IN ULONG BusInterruptLevel, void wake_up(wait_queue_head_t *q); SIZE_T Length, IN ULONG BusInterruptVector, void wake_up_interruptible(wait_queue_head_t *q); ULONG Alignment); – verifică un buffer din user-space OUT PKIRQL Irql, OUT PKAFFINITY Affinity); InterfaceType: Isa, Pci, Internal Userspace access ı̂n Linux Evenimente – events NTSTATUS IoConnectInterrupt( put_user(type val, type *address); KEVENT – structură aferentă unui eveniment (event) OUT PKINTERRUPT *InterruptObject, get_user(type val, type *address); VOID KeInitializeEvent( IN PKSERVICE_ROUTINE ServiceRoutine, unsigned long copy_to_user(void __user *to, const void PRKEVENT Event, IN PVOID ServiceContext, *from, unsigned long n); EVENT_TYPE Type, IN PKSPIN_LOCK SpinLock OPTIONAL, unsigned long copy_from_user(void *to, const void __user BOOLEAN State); – init, ializare eveniment IN ULONG Vector, *from, unsigned long n); LONG KeSetEvent( IN KIRQL Irql, PKEVENT Event, IN KIRQL SynchronizeIrql, KPRIORITY Increment, IN KINTERRUPT_MODE InterruptMode, Device drivere ı̂n Windows BOOLEAN Wait); – activare eveniment (stare signaled) IN BOOLEAN ShareVector, LONG KeReadStateEvent( IN KAFFINITY ProcessorEnableMask, DRIVER_OBJECT – obiect aferent unui driver IN BOOLEAN FloatingSave); PRKEVENT Event); – cites, te starea evenimentului DEVICE_OBJECT – obiect aferent unui dispozitiv InterruptMode: LevelSensitive, Latched IRP – I/O Request Pachet – ı̂mpachetarea unei cereri I/O VOID IoDisconnectInterrupt( IO_STACK_LOCATION – pozit, ia curentă din IRP ı̂n stiva de drivere I/O pe porturi IN PKINTERRUPT InterruptObject); \Device\MyDevice – nume de dispozitiv ı̂n kernel space BOOLEAN InterruptService( \??\MyDevice – symbolic link la nume Linux IN PKINTERRUPT Interrupt, \\.\MyDevice – nume de dispozitiv ı̂n user space #include <linux/ioport.h> IN PVOID ServiceContext); NTSTATUS IoCreateDevice( struct resource *request_region(unsigned long first, PDRIVER_OBJECT DriverObject, unsigned long n, const char *name); ULONG DeviceExtensionSize, void release_region(unsigned long start, unsigned long n); Sincronizare cu ı̂ntreruperi PUNICODE_STRING DeviceName, #include <asm/io.h> DEVICE_TYPE DeviceType, unsigned inb(unsigned port); Linux LONG DeviceCharacteristics, void outb(unsigned char byte, unsigned port); void disable_irq(unsigned int irq); BOOLEAN Exclusive, unsigned inw(unsigned port); – dezactivează o ı̂ntrerupere PDEVICE_OBJECT *DeviceObject); – crearea unui obiect void outw(unsigned short word, unsigned port); void disable_irq_nosync(unsigned int irq); dispozitiv unsigned inl(unsigned port); – dezactivează o ı̂ntrerupere fără a as, tepta terminarea NTSTATUS IoCreateSymbolicLink( void outl(unsigned long word, unsigned port); void enable_irq(unsigned int irq); PUNICODE_STRING SymbolicLinkName, Windows – activează o ı̂ntrerupere PUNICODE_STRING DeviceName); – crearea unui link simbolic UCHAR READ_PORT_UCHAR(PUCHAR Port); void local_irq_disable(void); (nume vizibil din user space) VOID WRITE_PORT_UCHAR(PUCHAR Port, UCHAR Value); – dezactivează ı̂ntreruperile pe procesorul curent NTSTATUS IoDeleteSymbolicLink( USHORT READ_PORT_USHORT(PUSHORT Port); void local_irq_enable(void); PUNICODE_STRING SymbolicLinkName); – s, tergerea unui link VOID WRITE_PORT_USHORT(PUSHORT Port, USHORT Value); – reactivează ı̂ntreruperile pe procesorul curent simbolic ULONG READ_PORT_ULONG(PULONG Port); void spin_lock_irq(spinlock_t *lock); NTSTATUS IoDeleteDevice( VOID WRITE_PORT_ULONG(PULONG Port, ULONG Value); – spin lock cu dezactivarea ı̂ntreruperilor PDEVICE_OBJECT DeviceObject); – s, tergerea unui obiect void spin_unlock_irq(spinlock_t *lock); dispozitiv Întreruperi – spin unlock cu reactivarea ı̂ntreruperilor device->DeviceExtension – zonă alocată pentru structura proprie a void spin_lock_irqsave(spinlock_t *lock, unui dispozitiv Linux unsigned long flags); driver->MajorFunction[] – vector pentru rutinele de dispatch #include <linux/interrupt.h> – + salvarea stării ı̂ntreruperilor expuse de driver int request_irq(unsigned int irq_no, void spin_unlock_irqrestore(spinlock_t *lock, NTSTATUS (*PDRIVER_DISPATCH)( irqreturn_t (*handler)(int irq_no, void *dev_id), unsigned long flags); PDEVICE_OBJECT DeviceObject, unsigned long flags, const char *dev_name, – + revenirea la starea salvată a ı̂ntreruperilor PIRP Irp); – rutină de dispatch pentru drivere void *dev_id); Windows flags: IRQF_SHARED, IRQF_SAMPLE_RANDOM, IRQF_DISABLED BOOLEAN KeSynchronizeExecution( Accesarea spat, iului de adresă din user space void free_irq(unsigned int irq_no, void *dev_id); IN PKINTERRUPT Interrupt, irqreturn_t my_handler(int irq_no, void *dev_id); IN PKSYNCHRONIZE_ROUTINE SynchronizeRoutine, PVOID MmGetSystemAddressForMdlSafe( irqreturn t: IRQ_HANDLED, IRQ_NONE IN PVOID SynchronizeContext); PMDL Mdl, Windows – execută SynchronizeRoutine la IRQL egal cu al ı̂ntreruperii MM_PAGE_PRIORITY Priority); – obt, ine o adresă non-paged ULONG HalGetInterruptVector( BOOLEAN mySynchronizeRoutine( aferentă bufferului descris de MDL IN INTERFACE_TYPE InterfaceType, PVOID Context); Act, iuni amânabile Locking softirq-uri Windows – System worker threads
Linux PIO_WORKITEM IoAllocateWorkItem(
Linux – Taskleti IN PDEVICE_OBJECT DeviceObject); DECLARE_TASKLET( void local_bh_disable(void); VOID IoFreeWorkItem( struct tasklet_struct *tasklet, void local_bh_enable(void); IN PIO_WORKITEM IoWorkItem); void (*function)(unsigned long), void spin_lock_bh(spinlock_t *lock); VOID IoQueueWorkItem( unsigned long data); void spin_unlock_bh(spinlock_t *lock); IN PIO_WORKITEM IoWorkItem, DECLARE_TASKLET_DISABLED( void read_lock_bh(rwlock_t *lock); IN PIO_WORKITEM_ROUTINE WorkerRoutine, struct tasklet_struct *tasklet, void read_unlock_bh(rwlock_t *lock); IN WORK_QUEUE_TYPE QueueType, void (*function)(unsigned long), void write_lock_bh(rwlock_t *lock); IN PVOID Context); unsigned long data); void write_unlock_bh(rwlock_t *lock); VOID WorkItem( void tasklet_init(struct tasklet_struct *tasklet); IN PDEVICE_OBJECT DeviceObject, IN PVOID Context); void tasklet_schedule(struct tasklet_struct *tasklet); Cozi de sarcini void tasklet_hi_schedule(struct tasklet_struct *tasklet); Linux – Workqueues Thread-uri kernel void tasklet_enable(struct task_struct *tasklet); void tasklet_disable(struct task_struct *tasklet); #include <linux/workqueue.h> Linux – Kernel threads Linux – Timere DECLARE_WORK( #include <linux/kthread.h> name, #include <linux/sched.h> #include <linux/sched.h> void (*function)( struct work_struct *)); void setup_timer( DECLARE_DELAYED_WORK( struct task_struct *kthread_create( struct timer_list *timer, name, int (*threadfn)(void *data), void (*function)(unsigned long), void (*function)( struct work_struct *)); void *data, const char namefmt[], ...); unsigned long data); INIT_WORK( struct task_struct *kthread_run( struct work_struct *work, int (*threadfn)(void *data), int mod_timer( void (*function)( struct work_struct *)); void *data, const char namefmt[], ...); struct timer_list *timer, INIT_DELAYED_WORK( int wake_up_process( unsigned long expires); struct delayed_work *work, struct task_struct *p); int del_timer(struct timer_list *timer); void (*function)( struct work_struct *)); fastcall NORET_TYPE void do_exit( int del_timer_sync(struct timer_list *timer); long code); schedule_work( Windows – DPC-uri struct work_struct *work); Windows – System threads schedule_delayed_work( NTSTATUS PsCreateSystemThread( VOID KeInitializeDpc( struct delayed_work *work, OUT PHANDLE ThreadHandle, IN PRKDPC Dpc, unsigned long delay); IN ULONG DesiredAccess, IN PKDEFERRED_ROUTINE DeferredRoutine, int cancel_delayed_work( IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN PVOID DeferredContext); struct delayed_work *work); IN HANDLE ProcessHandle OPTIONAL, VOID DeferredRoutine( void flush_scheduled_work( OUT PCLIENT_ID ClientId OPTIONAL, IN KDPC *Dpc, void); IN PKSTART_ROUTINE StartRoutine, IN PVOID DeferredContext, IN PVOID SystemArgument1, struct workqueue_struct *create_workqueue( IN PVOID StartContext); IN PVOID SystemArgument2); const char *name); VOID StartRoutine( BOOLEAN KeInsertQueueDpc( struct workqueue_struct *create_singlethread_workqueue( IN PVOID StartContext); IN PRKDPC Dpc, const char *name); NTSTATUS PsTerminateSystemThread( IN PVOID SystemArgument1, IN NTSTATUS ExitStatus); IN PVOID SystemArgument2); int queue_work( struct workqueue_struct *queue, Windows – Timere struct work_struct *work); Linux – I/O Block Layer int queue_delayed_work( VOID KeInitializeTimer( int register_blkdev( struct workqueue_struct *queue, IN PKTIMER Timer); unsigned int major, struct delayed_work *work, BOOLEAN KeSetTimer( const char *name); unsigned long delay); IN PKTIMER Timer, void unregister_blkdev( IN LARGE_INTEGER DueTime, void flush_workqueue( unsigned int major, IN PKDPC Dpc OPTIONAL); struct workqueue_struct *queue); const char *name); BOOLEAN KeCancelTimer( void destroy_workqueue( – ı̂nregistrare/deı̂nregistrarea unui dispozitiv de tip bloc IN PKTIMER Timer); struct workqueue_struct *queue); struct gendisk *alloc_disk(int minors); void del_gendisk(struct gendisk *disk); – demaparea unui bio dintr-un spat, iu din highmem pgprot_t prot) - mapează un spat, iu de memorie fizică ı̂n – alocarea/s, tergerea unui disc bio_sectors(bio); spat, iu virtual utilizator void add_disk(struct gendisk *disk); – numărul de sectoare cuprins de bio – adăugarea unui disc static inline unsigned int bio_cur_bytes(struct bio *bio); struct request_queue *blk_init_queue( – numărul de octet, i ocupat de bio Windows Memory Mapping request_fn_proc *rfn, bio_data_dir(bio); struct MDL - descrie layout-ul fizic al unui spat, iu de adresă virtual spinlock_t *lock); – direct, ia de parcurgere pentru bio (read/write) PMDL MmAllocatePagesForMdl( void blk_cleanup_queue(struct request_queue *q); bio_for_each_segment(bvl, bio, i); IN PHYSICAL_ADDRESS LowAddress, – crearea/s, tergerea unei cozi de cereri – parcurgerea fiecărui segment al unui bio IN PHYSICAL_ADDRESS HighAddress, typedef void (request_fn_proc) (struct request_queue *q); rq_for_each_segment(bvl, _rq, _iter); IN PHYSICAL_ADDRESS SkipBytes, typedef int (make_request_fn) ( – parcurgerea fiecărui segment al unei cereri IN SIZE_T TotalBytes) - alocare pagini fizice pentru MDL struct request_queue *q, VOID MmFreePagesFromMdl( struct bio *bio); IN PMDL MemoryDescriptorList) - eliberează pagini fizice – funct, ii pentru prelucrarea cererilor din coadă Windows – Lucrul cu dispozitive alocate unui MDL struct request *blk_peek_request(struct request_queue *q); NTKERNELAPI VOID MmMapLockedPagesSpecifyCache( NTSTATUS IoCreateDevice( void blk_start_queue(struct request_queue *q); IN PMDL MemoryDescriptorList, PDRIVER_OBJECT DriverObject, struct request *blk_fetch_request(struct request_queue *q); IN KPROCESSOR_MODE AccessMode, ULONG DeviceExtensionSize, void blk_requeue_request( IN MEMORY_CACHING_TYPE CacheType, PUNICODE_STRING DeviceName, struct request_queue *q, IN PVOID BaseAddress, DEVICE_TYPE DeviceType, struct request *rq); IN ULONG BugCheckOnFailure, ULONG DeviceCharacteristics, – funct, ii pentru lucrul cu cereri din coada de cereri IN MM_PAGE_PRIORITY Priority) - mapare ı̂ntre zone de BOOLEAN Exclusive, sector_t blk_rq_pos(const struct request *rq); memorie fizică s, i o zonă de memorie virtual contiguă VOID PDEVICE_OBJECT *DeviceObject); – creează un dispozitiv de unsigned int blk_rq_bytes(const struct request *rq); MmMapUnmapedLockedPages( tip DEVICE OBJECT int blk_rq_cur_bytes(const struct request *rq); IN PVOID BaseAddress, NTSTATUS IoGetDeviceObjectPointer( – obt, inerea numărului de sectoare s, i octet, i dintr-o cerere IN PMDL MemoryDescriptorList) - undo PUNICODE_STRING ObjectName, bool blk_end_request( MmMapLockedPagesSpecifyCache ACCESS_MASK DesiredAccess, struct request *rq, PVOID MmGetSystemAddressForMdlSafe( PFILE_OBJECT *FileObject, int error, IN PMDL Mdl, PDEVICE_OBJECT *DeviceObject); – obt, ine un pointer la unsigned int nr_bytes); IN MM_PAGE_PRIORITY Priority) - ı̂ntoarcere pointer către obiectul descris de ObjectName bool __blk_end_request( zona de memorie virtuală descrisă de un MDL VOID IoFreeMdl( VOID ObDereferenceObject(PVOID Object); – decrementarea struct request *rq, IN PMDL Mdl) - eliberare MDL contorului de referint, ă a unui obiect; opus la int error, IoGetDeviceObjectPointer unsigned int nr_bytes); PIRP IoBuildSynchronousFsdRequest( void blk_end_request_all(struct request *rq, int error);; ULONG MajorFunction, void __blk_end_request_all(struct request *rq, int error);; PDEVICE_OBJECT DeviceObject, – ı̂ncheierea unei cereri PVOID Buffer, struct bio *bio_alloc(gfp_t gfp_mask, int nr_iovecs); ULONG Length, – alocarea unui bio PLARGE_INTEGER StartingOffset, struct bio *bio_clone(struct bio *bio, gfp_t gfp_mask); PKEVENT Event, – clonarea unui bio existent ı̂ntr-un alt bio PIO_STATUS_BLOCK IoStatusBlock); – crearea unui IRP void submit_bio(int rw, struct bio *bio); pentru o cerere I/O procesată sincron – submiterea unui bio dispozitivului descris ı̂n structură NTSTATUS IoCallDriver( void complete(struct completion *x); PDEVICE_OBJECT DeviceObject, – marcarea unui eveniment (completion) ca fiind PIRP Irp); – transmiterea unui IRP unui dispozitiv ı̂ncheiat/realizat alloc_page(gfp_mask); – alocarea unei pagini Linux Memory Mapping int bio_add_page( struct bio *bio, struct page - descrie o pagină fizică struct page *page, struct vm_area_struct - descrie o zonă de memorie virtuală unsigned int len, struct mm_struct - descrie toate caracteristicile legate de memorie unsigned int offset); asociate unui proces – adăugarea unei pagini unui bio remap_pfn_range( __bio_kmap_atomic(bio, idx, kmtype); struct vm_area_struct *vma, – maparea unui bio ı̂ntr-un spat, iu din highmem unsigned long addr, __bio_kunmap_atomic(addr, kmtype); unsigned long pfn, unsigned long size,