Operating Systems 2017F Lecture 16: Difference between revisions
Line 7: | Line 7: | ||
==newgetpid.c== | ==newgetpid.c== | ||
<source lang="C" | <source lang="C" line> | ||
/* Code derived from: | /* Code derived from: | ||
https://appusajeev.wordpress.com/2011/06/18/writing-a-linux-character-device-driver/ | https://appusajeev.wordpress.com/2011/06/18/writing-a-linux-character-device-driver/ |
Revision as of 01:34, 10 November 2017
Video
The video from the lecture given on Nov. 7, 2017 is now available.
Code
newgetpid.c
/* Code derived from:
https://appusajeev.wordpress.com/2011/06/18/writing-a-linux-character-device-driver/
and
http://pete.akeo.ie/2011/08/writing-linux-device-driver-for-kernels.html
*/
#include <linux/module.h>
#include <linux/string.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <asm/uaccess.h>
#define dbg(format, arg...) do { if (debug) pr_info(CLASS_NAME ": %s: " format, __FUNCTION__, ## arg); } while (0)
#define err(format, arg...) pr_err(CLASS_NAME ": " format, ## arg)
#define info(format, arg...) pr_info(CLASS_NAME ": " format, ## arg)
#define warn(format, arg...) pr_warn(CLASS_NAME ": " format, ## arg)
#define DEVICE_NAME "newgetpid"
#define CLASS_NAME "comp3000"
static struct class* newgetpid_class = NULL;
static struct device* newgetpid_device = NULL;
static int newgetpid_major;
static int newgetpid_open(struct inode *the_inode, struct file *f)
{
return 0;
}
static ssize_t newgetpid_read(struct file *f, char *buf, size_t len, loff_t *offset)
{
size_t i, msglen;
pid_t thepid;
char message[100];
if (*offset > 0) {
return 0;
}
thepid = task_tgid_vnr(current);
snprintf(message, 100, "Your PID is %d!\n", thepid);
msglen = strlen(message);
if (len < msglen) {
msglen = len;
}
for (i = 0; i < msglen; i++) {
put_user(message[i], buf++);
}
*offset = i;
return i;
}
static int newgetpid_release(struct inode *the_inode, struct file *f)
{
printk(KERN_ALERT "Newgetpid device closed\n");
return 0;
}
static struct file_operations newgetpid_fops = {
.open = newgetpid_open,
.read = newgetpid_read,
.release = newgetpid_release,
};
static char *newgetpid_devnode(struct device *dev, umode_t *mode)
{
if (mode)
*mode = 0444;
return NULL;
}
static int __init newgetpid_init(void)
{
int retval;
newgetpid_major = register_chrdev(0, DEVICE_NAME, &newgetpid_fops);
if (newgetpid_major < 0) {
err("failed to register device: error %d\n", newgetpid_major);
retval = newgetpid_major;
goto failed_chrdevreg;
}
newgetpid_class = class_create(THIS_MODULE, CLASS_NAME);
if (IS_ERR(newgetpid_class)) {
err("failed to register device class '%s'\n", CLASS_NAME);
retval = PTR_ERR(newgetpid_class);
goto failed_classreg;
}
newgetpid_class->devnode = newgetpid_devnode;
newgetpid_device = device_create(newgetpid_class, NULL, MKDEV(newgetpid_major, 0),
NULL, DEVICE_NAME);
if (IS_ERR(newgetpid_device)) {
err("failed to create device '%s'\n", DEVICE_NAME);
retval = PTR_ERR(newgetpid_device);
goto failed_devreg;
}
info("Newgetpid device registered using major %d.\n", newgetpid_major);
return 0;
failed_devreg:
class_unregister(newgetpid_class);
class_destroy(newgetpid_class);
failed_classreg:
unregister_chrdev(newgetpid_major, DEVICE_NAME);
failed_chrdevreg:
return -1;
}
static void __exit newgetpid_exit(void)
{
device_destroy(newgetpid_class, MKDEV(newgetpid_major, 0));
class_unregister(newgetpid_class);
class_destroy(newgetpid_class);
unregister_chrdev(newgetpid_major, "newgetpid");
info("Unloading Newgetpid module.\n");
return;
}
module_init(newgetpid_init);
module_exit(newgetpid_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Anil Somayaji <soma@scs.carleton.ca>");
MODULE_DESCRIPTION("A write newgetpid character device module");
Makefile
obj-m := newgetpid.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules