-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
961 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -50,3 +50,5 @@ modules.order | |
Module.symvers | ||
Mkfile.old | ||
dkms.conf | ||
|
||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
CONFIG_MODULE_SIG=n | ||
WARN := -W -Wall -Wstrict-prototypes -Wmissing-prototypes | ||
ccflags-y := -O2 | ||
|
||
obj-m += mailslot.o | ||
mailslot-objs := ./src/mailslot_driver.o ./src/mailslot.o | ||
|
||
all: | ||
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules | ||
|
||
clean: | ||
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,71 @@ | ||
# LinuxMailslotsModule | ||
Windows mailslots for the Linux kernel | ||
<h1 align="center"> | ||
Linux Mailslots Module | ||
</h1> | ||
|
||
<h3 align="center">Windows mailslots for the Linux kernel</h3> | ||
|
||
<p align="center"> | ||
<a href="https://github.com/rikyoz/LinuxMailslotsModule/releases/latest"><img src="https://img.shields.io/github/release/rikyoz/LinuxMailslotsModule/all.svg?style=flat-square&logo=github&logoColor=white&colorB=blue" alt="GitHub release"></a> | ||
<img src="https://img.shields.io/badge/OS-Linux-red.svg?style=flat-square&logo=linux&logoColor=white" alt="MSVC version"> | ||
<img src="https://img.shields.io/badge/arch-x86,%20x86__64-orange.svg?style=flat-square&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAQAAAAAYLlVAAAC1UlEQVR42u3WA9AjWRSA0bu2bdu2bdssrm3btm3btm3bmX+Ms7rLTiW9NUmvcsL7XuELu6Ojoz5DWcc5nvKp2kBdPvesi21m1Pgr7OxjrfWtgw0VZZjKM9rjXfNHM+bWWzutGo2YSH/tNm+jgNe1XzdDR322V41Tox5D6K4qY0WRtVRnjyhysercH0VeVJ13o8hXqvNNFOlSna4oUlOd2r8moBPwoQfd6THfoLweauqp6aJ8wInmMmjujWAFtwMeNJup5cXsVnWYDyDtajQjmMp7QOoypxGMbMtyAe+Ztf5/JTaJAkM6mjRXrj0KpE9zdZIyAV8bLX5lBIPlszXAVlGXMwAr5fwskL4wdPzAfGUC5o9kJy+o+dCVloiwJNg2907wimddZrqcB9GtNQF3RXI+kI5yCcgADwF6yvfLNa0JWD7n5dWXAa4lbZwrR7UioKdhc76vdEB+KxzbioAncxpGr9IBM+XKDa0IuCanaWkS8BzguEhqrQg4P6e5mgasbV+7WCySvWlFwIU5zdYooMhytCbghpzGLh9gAodCWjFXXwDSV4aJH5inWcBLkbzTOMBa9rWvk92jH5BWqBvwjSHKBfQ3as4HlvoSFq2b+zcB6bXIj6pZABvnPKzPgPSJlxV/hkUH5v7SUPiv2LN5wKuRjO82wDdON6xFSwW8XvhdcGYkrzUPYJf4lcktZh4jxg8sViqA9SKZxDo2NH0km1ImgE2jDjuBLXK6FPX1N1fUYQnKBnCeGeN3jGdPfUC+P27TyO7GjN8xoUMpHZCecKZ97etE9+hD6vKQOz1jgMa6u90J+VO9V//OaXnzgE5Al+p0iyLfqM63UeRV1Xk/ilylOo9Gkc1U55AoMrz+qjJJ1OMQ1bgq6jOYr1Rh9EgFZtd+q0QjVtFeW0UzFvGJ9uhhrSjDSE7UX6tdaMIoz0R2cbvXfKE2UJevvOEe+5kuOjr+qb4H0/HV/SQ0YjEAAAAASUVORK5CYII=" alt="Architectures"> | ||
<a href="https://github.com/rikyoz/bit7z/blob/master/LICENSE"><img src="https://img.shields.io/badge/license-GNU%20GPL%20v2-lightgrey.svg?style=flat-square&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAQAAAAAYLlVAAAAvUlEQVR42u3Zt1EEURRE0Ye0gFwI4BWJoC0KGxftExk+RQATAN+nLpo1R0+v6NsJHPOLcO4vKkrPVexEcMFZN8AQ7UXwCBx0ART6VtiN4BCA1AHO+SnVAEg1AFINgFQDINUASDUAUg2AVAMg1QBINQBSDYBUAyDVAMhxAVfUdzkmYJ+7mj1xPQ7gjbWYJTmQbGsB77zy0mjPPQH9UwOKAQYYYIABBhhggAFzCTDAAAMMMGDS+v2a9V8Vzs1PH+dRolvEzoAoAAAAAElFTkSuQmCC" alt="License"></a> | ||
</p> | ||
<p align="center"> | ||
<a href="#features">Features</a> • | ||
<a href="#building">Building</a> • | ||
<a href="#usage">Usage</a> • | ||
<a href="#license-gpl-v2">License</a> | ||
</p> | ||
|
||
This project provides a simple and easy to use Linux kernel module implementing a service similar to Windows mailslots, i.e. a driver for special device files accessible according to FIFO policy. | ||
|
||
Developed for the course of *Advanced Operating Systems and Virtualization* (AOSV) taken in the A.Y. 2016/2017 for the *Master Degree in Engineering in Computer Science* (MSE-CS) at *Sapienza University of Rome*. | ||
The original project specification can be found [here](https://www.dis.uniroma1.it/~quaglia/DIDATTICA/AOSV/examination.html). | ||
|
||
## Features | ||
The module is a Linux driver for special device files supporting the following features: | ||
|
||
+ **FIFO** (**F**irst **I**n **F**irst **O**ut) access policy semantic (via *open/close/read/write* services). | ||
+ **Atomic** message read/write, i.e. any segment read from or written to the file stream is seen as an independent data unit, a message, and it is posted/delivered atomically (all or nothing). | ||
+ Support to **multiple instances** accessible concurrently by active processes/threads. | ||
+ **Blocking/Non-Blocking** runtime behaviour of I/O sessions (tunable via *open* or *ioctl* commands) | ||
+ Runtime configuration (via ioctl) of the following parameters: | ||
+ *Maximum message size* (configurable up to an absolute upper limit). | ||
+ *Maximum mailslot storage size* which is dynamically reserved to any individual mailslot. | ||
+ Compile-time configuration of the following parameters: | ||
+ *Range of device file minor numbers* supported by the driver (default: [0-255]). | ||
+ *Number of mailslot instances* (default: 256). | ||
|
||
## Building | ||
|
||
The project provides a Makefile and can be compiled using the `make` command line utility. | ||
|
||
## Usage | ||
|
||
Once built, the module can be manually installed using the `insmod mailslot.ko` command (or via the `install.sh` utility shell script, which installs the module and creates also 3 mailslots files in the `/dev/` directory). | ||
Mailslot files can be created using the `mknod` command (for example usages, please see the `install.sh` script), | ||
|
||
In order to uninstall the module, the `rmmod mailslot` command must be used, as well as mailslot files can removed using the `rm` command (if the installation script was used, the module can also be uninstalled using the provided `uninstall.sh` shell script, which removes also the 3 mailslots files created during the installation). | ||
|
||
## License (GPL v2) | ||
|
||
This program is free software; you can redistribute it and/or modify | ||
it under the terms of the GNU General Public License as published by | ||
the Free Software Foundation; either version 2 of the License, or | ||
(at your option) any later version. | ||
|
||
This program is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
GNU General Public License for more details. | ||
|
||
You should have received a copy of the GNU General Public License along | ||
with this program; if not, write to the Free Software Foundation, Inc., | ||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
|
||
<br/> | ||
<div align="center"> | ||
|
||
Copyright © 2017 - 2018 Riccardo Ostani ([@rikyoz](https://github.com/rikyoz)) | ||
|
||
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
#!/bin/bash | ||
insmod mailslot.ko | ||
|
||
#reading major number of the mailslot driver | ||
mailslot_major=$( cat /proc/devices | grep mailslot | cut -d " " -f 1 ) | ||
|
||
#inserting device file in /dev/ | ||
mknod -m 666 /dev/mailslot0 c $mailslot_major 0 | ||
mknod -m 666 /dev/mailslot1 c $mailslot_major 1 | ||
mknod -m 666 /dev/test_mailslot c $mailslot_major 2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,213 @@ | ||
/* | ||
Copyright (C) 2017-2018 Riccardo Ostani. | ||
This program is free software; you can redistribute it and/or | ||
modify it under the terms of the GNU General Public License | ||
as published by the Free Software Foundation; either version 2 | ||
of the License, or (at your option) any later version. | ||
This program is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
GNU General Public License for more details. | ||
You should have received a copy of the GNU General Public License | ||
along with this program; if not, write to the Free Software | ||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
*/ | ||
|
||
#include "mailslot.h" | ||
|
||
#include <linux/slab.h> /* for kzalloc */ | ||
#include <linux/mutex.h> /* for mutex */ | ||
#include <linux/uaccess.h> /* for copy_to_user and copy_from_user functions */ | ||
#include <linux/wait.h> /* for wait_queue */ | ||
|
||
typedef struct message { | ||
char* content; | ||
size_t size; | ||
struct message* next; | ||
} message_t; | ||
|
||
struct mailslot { | ||
struct mutex mutex; | ||
wait_queue_head_t rd_queue, wr_queue; | ||
message_t* head; | ||
message_t* tail; | ||
size_t max_msg_size; | ||
int msg_count; | ||
int id; /* needed only to help debugging! */ | ||
}; | ||
|
||
mailslot_t* mailslot_alloc( void ) { | ||
return kzalloc( sizeof( mailslot_t ), GFP_KERNEL ); | ||
} | ||
|
||
void mailslot_init( mailslot_t* slot, int id ) { | ||
mutex_init( &( slot->mutex ) ); | ||
init_waitqueue_head( &( slot->rd_queue ) ); | ||
init_waitqueue_head( &( slot->wr_queue ) ); | ||
slot->head = NULL; | ||
slot->tail = NULL; | ||
slot->max_msg_size = DEFAULT_MAX_MSG_SIZE; | ||
slot->id = id; | ||
} | ||
|
||
ssize_t mailslot_enqueue( mailslot_t* slot, const char* content, size_t size, int non_blocking ) { | ||
int error; | ||
int count = slot->msg_count; | ||
message_t* msg = NULL; | ||
|
||
if ( count == MAX_SLOT_SIZE ) { | ||
printk( KERN_ERR "mailslot (id %d): cannot enqueue msg, slot is full\n", slot->id ); | ||
return -ENOSPC; | ||
} | ||
|
||
if ( size > slot->max_msg_size ) { /* all or nothing */ | ||
printk( KERN_ERR "mailslot (id %d): cannot write msg, size (%lu) greater than max allowed by the slot (%lu)\n", slot->id, size, slot->max_msg_size ); | ||
return -EPERM; | ||
} | ||
|
||
msg = kzalloc( sizeof( message_t ), non_blocking ? GFP_ATOMIC : GFP_KERNEL ); | ||
if ( msg == NULL ) { | ||
printk( KERN_ERR "mailslot (id %d): failed to allocate space for the new msg\n", slot->id ); | ||
return non_blocking ? -EAGAIN : -ENOMEM; | ||
} | ||
|
||
msg->content = kzalloc( size, non_blocking ? GFP_ATOMIC : GFP_KERNEL ); | ||
if ( msg->content == NULL ) { | ||
printk( KERN_ERR "mailslot (id %d): failed to allocate space for the new msg's content\n", slot->id ); | ||
kfree( msg ); | ||
return non_blocking ? -EAGAIN : -ENOMEM; | ||
} | ||
|
||
if ( non_blocking ) { /* disabling the pagefault handler, so that copy_from_user won't sleep */ | ||
pagefault_disable(); | ||
} | ||
error = copy_from_user( msg->content, content, size ); | ||
if ( non_blocking ) { | ||
pagefault_enable(); | ||
} | ||
if ( error ) { | ||
printk( KERN_ERR "mailslot (id %d): failed to copy msg from user space\n", slot->id ); | ||
kfree( msg->content ); | ||
kfree( msg ); | ||
return -EFAULT; | ||
} | ||
msg->size = size; | ||
msg->next = NULL; | ||
|
||
if ( count == 0 ) { | ||
slot->head = msg; | ||
} else { | ||
slot->tail->next = msg; | ||
} | ||
slot->tail = msg; | ||
slot->msg_count++; | ||
mailslot_printqueue( slot ); /* debug help */ | ||
|
||
return size; | ||
} | ||
|
||
ssize_t mailslot_dequeue( mailslot_t* slot, char* buffer, size_t size, int non_blocking ) { | ||
int res, error; | ||
int count = slot->msg_count; | ||
message_t* msg = NULL; | ||
|
||
if ( count == 0 ) { /* not an error */ | ||
printk( KERN_INFO "mailslot (id %d): no msg to read, empty slot\n", slot->id ); | ||
return 0; | ||
} | ||
|
||
msg = slot->head; | ||
if ( msg->size > size ) { /* all or nothing */ | ||
printk( KERN_ERR "mailslot (id %d): user buffer too small for the msg\n", slot->id ); | ||
return -EMSGSIZE; | ||
} | ||
|
||
if ( non_blocking ) { | ||
pagefault_disable(); | ||
} | ||
error = copy_to_user( buffer, msg->content, msg->size ); | ||
if ( non_blocking ) { | ||
pagefault_enable(); | ||
} | ||
if ( error ) { | ||
printk( KERN_ERR "mailslot (id %d): failed to copy msg to user space\n", slot->id ); | ||
return -EFAULT; | ||
} | ||
|
||
res = msg->size; | ||
slot->head = slot->head->next; /* if count == 1, here head becomes NULL! */ | ||
kfree( msg->content ); | ||
kfree( msg ); | ||
if ( count == 1 ) { | ||
slot->tail = NULL; /* here head == NULL and tail == (deallocated) msg */ | ||
} | ||
slot->msg_count--; | ||
mailslot_printqueue( slot ); /* debug help */ | ||
|
||
return res; | ||
} | ||
|
||
int mailslot_lock( mailslot_t* slot, int non_blocking ) { | ||
printk( KERN_INFO "mailslot (id %d): pid %d wants to lock the slot", slot->id, current->pid ); | ||
if ( non_blocking ) { | ||
printk( KERN_CONT " without blocking\n" ); | ||
return mutex_trylock( &(slot->mutex) ); | ||
} else { | ||
printk( KERN_CONT "\n" ); | ||
return mutex_lock_interruptible( &(slot->mutex) ) == 0; | ||
} | ||
} | ||
|
||
void mailslot_unlock( mailslot_t* slot ) { | ||
mutex_unlock( &(slot->mutex) ); | ||
} | ||
|
||
int mailslot_wait_msg( mailslot_t* slot ) { | ||
return wait_event_interruptible_exclusive( slot->rd_queue, slot->msg_count > 0 ); | ||
} | ||
|
||
int mailslot_wait_space( mailslot_t* slot ) { | ||
return wait_event_interruptible_exclusive( slot->wr_queue, slot->msg_count < MAX_SLOT_SIZE ); | ||
} | ||
|
||
void mailslot_notify_msg( mailslot_t* slot ) { | ||
wake_up_interruptible( &(slot->rd_queue) ); | ||
} | ||
|
||
void mailslot_notify_space( mailslot_t* slot ) { | ||
wake_up_interruptible( &(slot->wr_queue) ); | ||
} | ||
|
||
void mailslot_set_max_msg_size( mailslot_t* slot, size_t size ) { | ||
slot->max_msg_size = size; | ||
} | ||
|
||
void mailslot_free( mailslot_t* slot ) { | ||
int i; | ||
message_t* msg = NULL; | ||
for ( i = 0; i < slot->msg_count; i++ ) { | ||
msg = slot->head->next; | ||
kfree( slot->head->content ); | ||
kfree( slot->head ); | ||
slot->head = msg; | ||
} | ||
kfree( slot ); | ||
} | ||
|
||
void mailslot_printqueue( mailslot_t* slot ) { | ||
message_t* msg = slot->head; | ||
printk( KERN_INFO "mailslot (id %d): (slot content) head = ", slot->id ); | ||
while ( msg != NULL ) { | ||
printk( KERN_CONT "\"%s\"", msg->content ); | ||
if ( msg->next != NULL ) { | ||
printk( KERN_CONT ", " ); | ||
} | ||
msg = msg->next; | ||
} | ||
if ( msg == NULL ){ | ||
printk( KERN_CONT " = tail\n" ); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
/* | ||
Copyright (C) 2017-2018 Riccardo Ostani. | ||
This program is free software; you can redistribute it and/or | ||
modify it under the terms of the GNU General Public License | ||
as published by the Free Software Foundation; either version 2 | ||
of the License, or (at your option) any later version. | ||
This program is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
GNU General Public License for more details. | ||
You should have received a copy of the GNU General Public License | ||
along with this program; if not, write to the Free Software | ||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
*/ | ||
|
||
#ifndef MAILSLOT_H | ||
#define MAILSLOT_H | ||
|
||
#include <linux/kernel.h> | ||
|
||
#define DEFAULT_MAX_MSG_SIZE 256 /* default max size of a message data-unit */ | ||
#define LIMIT_MAX_MSG_SIZE 512 /* upper limit to the max size of a message data-unit */ | ||
#define MAX_SLOT_SIZE 64 /* max number of messages storable in a mailslot */ | ||
|
||
typedef struct mailslot mailslot_t; | ||
|
||
/* Allocates a mailslot struct. */ | ||
mailslot_t* mailslot_alloc( void ); | ||
|
||
/* Initilizes the fields of a mailslot. */ | ||
void mailslot_init( mailslot_t* slot, int id ); | ||
|
||
/* Enqueues a message in a slot. | ||
* Note: it must be called in a critical section (e.g. after a mailslot_lock) */ | ||
ssize_t mailslot_enqueue( mailslot_t* slot, const char* content, size_t size, int non_blocking ); | ||
|
||
/* Dequeues the oldest message in the slot. | ||
* Note: it must be called in a critical section (e.g. after a mailslot_lock) */ | ||
ssize_t mailslot_dequeue( mailslot_t* slot, char* buffer, size_t size, int non_blocking ); | ||
|
||
/* Locks the access to the slot. | ||
* It returns 1 if lock was acquired, 0 otherwise. */ | ||
int mailslot_lock( mailslot_t* slot, int non_blocking ); | ||
|
||
/* Unlocks the access to the slot. */ | ||
void mailslot_unlock( mailslot_t* slot ); | ||
|
||
/* Makes the caller sleep and wait for a message to be written in the slot. */ | ||
int mailslot_wait_msg( mailslot_t* slot ); | ||
|
||
/* Makes the caller sleep and wait for space availability in the slot. */ | ||
int mailslot_wait_space( mailslot_t* slot ); | ||
|
||
/* Wakes up all processes waiting for new messages in the slot. */ | ||
void mailslot_notify_msg( mailslot_t* slot ); | ||
|
||
/* Wakes up all processes waiting for space in the slot. */ | ||
void mailslot_notify_space( mailslot_t* slot ); | ||
|
||
/* Sets the max message size allowed in the slot. */ | ||
void mailslot_set_max_msg_size( mailslot_t* slot, size_t size ); | ||
|
||
/* Frees the mailslot memory. */ | ||
void mailslot_free( mailslot_t* slot ); | ||
|
||
/* Prints the content of the slot fifo queue. */ | ||
void mailslot_printqueue( mailslot_t* slot ); | ||
|
||
#endif |
Oops, something went wrong.