Linux Device Driver -- file operations not working - c

I have recently updated my kernel and I am no longer able to use a previously written device drivers. My driver's init and exit functions work fine and log a message to the kernel log. However, I am no longer able to write, read, ioctl, open, or release the file. The functions do not print anything into the log file. I am compiling against linux-headers-5.4.79-v7l+.
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/kdev_t.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
MODULE_LICENSE("Dual BSD/GPL");
#define DEVICE_NAME "device"
static int device_open(struct inode *, struct file *);
static int device_release(struct inode *, struct file *);
static ssize_t device_read(struct file *, char *, size_t, loff_t *);
static ssize_t device_write(struct file *, const char *, size_t, loff_t *);
static long int device_ioctl(struct file *, unsigned int, unsigned long);
static struct file_operations fops =
{
owner: THIS_MODULE,
read: device_read,
write:device_write,
unlocked_ioctl: device_ioctl,
open: device_open,
release: device_release
};
struct cdev *device_cdev;
dev_t deviceNumbers;
static int init(void)
{
int ret = alloc_chrdev_region(&deviceNumbers, 0, 1, DEVICE_NAME);
if (ret < 0) {
printk(KERN_ALERT "Error registering: %d", ret);
return -1;
}
device_cdev = cdev_alloc();
cdev_init(device_cdev, &fops);
ret = cdev_add(device_cdev, deviceNumbers, 1);
printk(KERN_INFO "Device initialized");
return 0;
}
static void cleanup(void)
{
unregister_chrdev_region(deviceNumbers, 1);
cdev_del(device_cdev);
printk(KERN_INFO "Device unloaded");
}
static int device_open(struct inode *inode, struct file *file)
{
printk(KERN_INFO "Device open");
return 0;
}
static int device_release(struct inode *inode, struct file *file)
{
printk(KERN_INFO "Device released");
return 0;
}
static ssize_t device_write(struct file *filp, const char *buff, size_t len, loff_t * off)
{
printk(KERN_INFO "Device write");
return 0;
}
static ssize_t device_read(struct file *filp, char *buff, size_t len, loff_t * off)
{
printk(KERN_INFO "Device read");
return 0;
}
static long int device_ioctl(struct file *file, unsigned int ioctl_num, unsigned long ioctl_param)
{
printk(KERN_INFO "Device IOCTL");
return 0;
}
module_init(init);
module_exit(cleanup);

You should add terminating "\n" at the end of your prints to force their flush into the kernel log buffer. Here is your module with some enhancement suggestions:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/kdev_t.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
MODULE_LICENSE("Dual BSD/GPL");
#define DEVICE_NAME "device"
static int device_open(struct inode *, struct file *);
static int device_release(struct inode *, struct file *);
static ssize_t device_read(struct file *, char *, size_t, loff_t *);
static ssize_t device_write(struct file *, const char *, size_t, loff_t *);
static long int device_ioctl(struct file *, unsigned int, unsigned long);
static const struct file_operations fops =
{
.owner= THIS_MODULE,
.read= device_read,
.write=device_write,
.unlocked_ioctl= device_ioctl,
.open= device_open,
.release= device_release
};
struct cdev *device_cdev;
dev_t deviceNumbers;
static int __init init(void) // <------ Add __init keyword for kernel cleanups
{
// This returns the major number chosen dynamically in deviceNumbers
int ret = alloc_chrdev_region(&deviceNumbers, 0, 1, DEVICE_NAME);
if (ret < 0) {
printk(KERN_ALERT "Error registering: %d\n", ret);
return -1;
}
device_cdev = cdev_alloc();
cdev_init(device_cdev, &fops);
ret = cdev_add(device_cdev, deviceNumbers, 1);
printk(KERN_INFO "Device initialized (major number is %d)\n", MAJOR(deviceNumbers));
return 0;
}
static void __exit cleanup(void) // <------ Add __exit keyword for kernel cleanups
{
unregister_chrdev_region(deviceNumbers, 1);
cdev_del(device_cdev);
printk(KERN_INFO "Device unloaded\n");
}
static int device_open(struct inode *inode, struct file *file)
{
printk(KERN_INFO "Device open\n");
return 0;
}
static int device_release(struct inode *inode, struct file *file)
{
printk(KERN_INFO "Device released\n");
return 0;
}
static ssize_t device_write(struct file *filp, const char *buff, size_t len, loff_t * off)
{
printk(KERN_INFO "Device write\n");
return len; // <-------------- To stop the write
}
static ssize_t device_read(struct file *filp, char *buff, size_t len, loff_t * off)
{
printk(KERN_INFO "Device read\n");
return len; // <-------------- To stop the read
}
static long int device_ioctl(struct file *file, unsigned int ioctl_num, unsigned long ioctl_param)
{
printk(KERN_INFO "Device IOCTL\n");
return 0;
}
module_init(init);
module_exit(cleanup);
Check the current settings for the kernel log level.
$ cat /proc/sys/kernel/printk
4 4 1 7
In the preceding, the first column specifies that only messages with a log level lower than 4 will be printed.
The values accepted by printk() are:
KERN_EMERG 0 System is unusable
KERN_ALERT 1 Action must be taken immediately
KERN_CRIT 2 Critical conditions
KERN_ERR 3 Error conditions
KERN_WARNING 4 Warning conditions
KERN_NOTICE 5 Normal but significant condition
KERN_INFO 6 Informational
KERN_DEBUG 7 Debug-level messages
So, the KERN_INFO level is 6 which is greater than 4!
We modify the configuration:
$ sudo sh -c "echo 7 4 1 7 > /proc/sys/kernel/printk"
$ cat /proc/sys/kernel/printk
7 4 1 7
I built your module with the suggested modifications and tried it on Linux 5.4.0-58:
$ uname -a
Linux xxxx 5.4.0-58-generic #64-Ubuntu SMP Wed Dec 9 08:16:25 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
$ sudo insmod ./device.ko
$ dmesg
[...]
[ 7244.516706] Device initialized (major number is 235)
$ lsmod
Module Size Used by
device 16384 0
[...]
$ cat /proc/devices
Character devices:
[...]
235 device
$ sudo mknod /dev/device c 235 0
$ ls -l /dev/device
crw-r--r-- 1 root root 235, 0 janv. 3 10:33 /dev/device
$ sudo sh -c "echo foo > /dev/device"
$ dmesg
[...]
[ 7244.516706] Device initialized (major number is 235)
[ 7311.507652] Device open
[ 7311.507672] Device write
[ 7311.507677] Device released
$ sudo rmmod device
$ dmesg
[...]
[ 7244.516706] Device initialized (major number is 235)
[ 7311.507652] Device open
[ 7311.507672] Device write
[ 7311.507677] Device released
[ 7361.523964] Device unloaded
$ sudo rm /dev/device

Related

writing driver - "Failed to register device class"

I am trying to write a character device driver based on this tutorial.
But when trying to insert my module I get the following error:
$ sudo insmod modules/main/main.ko
insmod: ERROR: could not insert module modules/main/main.ko: Operation not permitted
$dmesg
[ 1085.409026] Failed to register device class
This is the corresponding code snippet:
#ifndef __KERNEL__
#define __KERNEL__
#endif
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#define CLASS_NAME "my_class"
#define DEV_NAME "my_device"
static int dev_open(struct inode *, struct file *);
static int dev_release(struct inode *, struct file *);
static ssize_t dev_read(struct file *, char *, size_t, loff_t *);
static ssize_t dev_write(struct file *, const char *, size_t, loff_t *);
static int myCharClass;
static int myCharDevice;
int majorNumber;
static struct file_operations fops =
{
.open = dev_open,
.read = dev_read,
.write = dev_write,
.release = dev_release
};
int init_module(void)
{
printk("Hello world - DAO \n");
majorNumber = register_chrdev(0, DEV_NAME, &fops);
if (majorNumber < 0)
{
printk("Error when registering character device driver.\n");
return -1;
}
myCharClass = class_create(THIS_MODULE, CLASS_NAME);
if (IS_ERR(myCharClass))
{
unregister_chrdev(majorNumber, DEV_NAME);
printk(KERN_ALERT "Failed to register device class\n");
return -1;
}
myCharDevice = device_create(myCharClass, NULL, MKDEV(majorNumber, 0), NULL, DEV_NAME);
if (IS_ERR(myCharDevice))
{
class_destroy(myCharClass);
unregister_chrdev(majorNumber, DEV_NAME);
printk(KERN_ALERT "Failed to create the device\n");
return -1;
}
return 0;
}
void cleanup_module(void)
{
printk("<1> Ciao - DAO\n");
}
static int dev_open(struct inode *p_inode, struct file *p_file)
{
printk("Opened device.\n");
return 0;
}
static ssize_t dev_read(struct file *filep, char *buffer, size_t len, loff_t *offset)
{
printk("Reading device.\n");
return 0;
}
static ssize_t dev_write(struct file *filep, const char *buffer, size_t len, loff_t *offset)
{
printk("Writing device\n");
return 0;
}
static int dev_release(struct inode *inodep, struct file *filep)
{
printk("Releasing device.\n");
return 0;
}
MODULE_LICENSE("GPL");
Does anybody know what I am doing incorrectly?
I had a look at this post, but it didn't really help me, because I didn't really what the issue is.
Thanks

insmod: ERROR: Could not insert module : No such device

I'm trying to implement character device driver in C at Linux.
My code is as follows:
#include<linux/device.h>
#include<linux/init.h>
#include<linux/kernel.h>
#include<linux/module.h>
#include<linux/fs.h>
#include<linux/err.h>
#include<asm/uaccess.h>
#define SUCCESS 0
#define DEVICE_NAME "chardev"
#define BUF_LEN 80
MODULE_LICENSE("GPL");
static int Major;
static char msg[BUF_LEN]={0};
static short s_o_msg;
static int Device_Open = 0;
static struct class* chardevClass = NULL;
static struct device* chardevDevice = NULL;
static char *msg_Ptr;
static int device_open(struct inode *, struct file *);
static int device_release(struct inode *, struct file *);
static ssize_t device_read(struct file *, char *, size_t, loff_t *);
static ssize_t device_write(struct file *, const char *, size_t, loff_t *);
static struct file_operations fops = {
.read = device_read,
.write = device_write,
.open = device_open,
.release = device_release
};
static int __init chardev_init(void){
Major = register_chrdev(0, DEVICE_NAME, &fops);
if (Major < 0) {
printk(KERN_ALERT "Registering char device failed with %d\n", Major);
return Major;
}
chardevDevice = device_create(chardevClass, NULL, MKDEV(Major,0), NULL, DEVICE_NAME);
if (IS_ERR(chardevDevice)) {
class_destroy(chardevClass);
unregister_chrdev(Major, DEVICE_NAME);
printk(KERN_ALERT
"Failed to create the device\n");
return PTR_ERR(chardevDevice);
}
printk(KERN_INFO "I was assigned major number %d. To talk to\n", Major);
printk(KERN_INFO "the driver, create a dev file with\n");
printk(KERN_INFO "'mknod /dev/%s c %d 0'.\n", DEVICE_NAME, Major);
printk(KERN_INFO "Try various minor numbers. Try to cat and echo to\n");
printk(KERN_INFO "the device file.\n");
printk(KERN_INFO "Remove the device file and module when done.\n");
return SUCCESS;
}
static void __exit chardev_exit(void){
device_destroy(chardevClass, MKDEV(Major, 0));
class_unregister(chardevClass);
class_destroy(chardevClass);
unregister_chrdev(Major, DEVICE_NAME);
printk(KERN_INFO "Goodbye!\n");
}
static int device_open(struct inode *inodep, struct file *filep)
{
static int counter = 0;
if (Device_Open)
return -EBUSY;
Device_Open++;
sprintf(msg, "I already told you %d times Hello world!\n", counter++);
msg_Ptr = msg;
try_module_get(THIS_MODULE);
return SUCCESS;
}
static ssize_t device_read(struct file *filep, char *buffer, size_t length, loff_t * offset){
int bytes_read = 0;
if (*msg_Ptr == 0)
return 0;
while (length && *msg_Ptr) {
put_user(*(msg_Ptr++), buffer++);
length--;
bytes_read++;
}
return bytes_read;
}
static int device_release(struct inode *inodep, struct file *filep)
{
Device_Open--;
module_put(THIS_MODULE);
return 0;
}
static ssize_t device_write(struct file *filep, const char *buffer, size_t length, loff_t *offset){
sprintf(msg, "%s(%zu letters)", buffer, length);
s_o_msg = strlen(msg);
printk(KERN_INFO "Received %zu characters from the user\n", length);
return length;
}
module_init(chardev_init);
module_exit(chardev_exit);
then, I compile this with following command and to this moment everything looks just fine:
obj-m := memory.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
but when I tried to run this module with
sudo /sbin/insmod memory.ko
I get an error :
insmod: ERROR: Could not insert module : No such device
Could you explain me please what I'm doing wrong and what should I do to run this module properly?
Thanks a lot.
You forget to create the class( class_create) before device_create() because if you see
root#achal:/sys/class# ls
.. there are so many different class..
your device also should be in one class that's why create one class using class_create();
Add below line in your code.
chardevClass = class_create(THIS_MODULE, "overflow");
chardevDevice = device_create(chardevClass, NULL, MKDEV(Major,0), NULL, DEVICE_NAME);
root mode is required for inserting a module, Sequence for compiling, inserting and running a module are :
First do make
root#root:~/s_flow# make
then do insmod & analyse dmesg output
root#root:~/s_flow# insmod memory.ko
root#root:~/s_flow# dmesg
..
.. check here whether __init chardev_init() is invoked or not
or you can check modinfo also
root#root:~/s_flow# modifno memory.ko
I hope it helps.

IOCTL call not working with driver

I wrote a IOCTL driver and a corresponding ioctl app with a header file containing commands.
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kdev_t.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>
#include "myioctl.h"
#include <linux/ioctl.h>
#define NAME MyCharDevice
//Function Prototypes
int NAME_open(struct inode *inode, struct file *filp);
int NAME_release(struct inode *indoe, struct file *filp);
ssize_t NAME_write(struct file *filp, char __user *Ubuff, size_t count, loff_t *offp);
ssize_t NAME_read(struct file *filp, char __user *Ubuff, size_t count, loff_t *offp);
int NAME_flush (struct file *filp);
int NAME_IOCTL (struct inode *inode, struct file *filp, unsigned long cmd, unsigned long val);
//Structure that defines the operations that the driver provides
struct file_operations fops =
{
.owner = THIS_MODULE,
.open = NAME_open,
.read = NAME_read,
.write = NAME_write,
.unlocked_ioctl = NAME_IOCTL,
.release = NAME_release,
.flush = NAME_flush,
};
//Structure for a character driver
struct cdev *my_cdev;
//Init Module
static int __init CharDevice_init(void)
{
int result;
int MAJOR,MINOR;
dev_t Mydev;
Mydev = MKDEV(255,0);//Create a device number
MAJOR=MAJOR(Mydev);
MINOR=MINOR(Mydev);
printk("\nThe Major Number is %d...THe Minor Number is %d\n",MAJOR,MINOR);
result=register_chrdev_region(Mydev,1,"MyCharDevice");//register device region.....
if(result<0)
{
printk(KERN_ALERT "\nThe Region requested for is not obtainable\n");
return(-1);
}
my_cdev = cdev_alloc();//allocate memory to Char Device structure
my_cdev->ops = &fops;//link our file operations to the char device
result=cdev_add(my_cdev,Mydev,1);//Notify the kernel abt the new device
if(result<0)
{
printk(KERN_ALERT "\nThe Char Devide has not been created......\n");
return (-1);
}
return 0;
}
//Cleanup Module
void __exit CharDevice_exit(void)
{
dev_t Mydev;
int MAJOR,MINOR;
Mydev=MKDEV(255,0);
MAJOR=MAJOR(Mydev);
MINOR=MINOR(Mydev);
printk("\nThe Major Number is %d...THe Minor Number is %d\n",MAJOR,MINOR);
unregister_chrdev_region(Mydev,1);//unregister the device numbers and the device created
cdev_del(my_cdev);
printk(KERN_ALERT "\nI have unregistered the stuff that was allocated.....Goodbye for ever.....\n");
return;
}
int NAME_IOCTL (struct inode *inode, struct file *filp, unsigned long cmd, unsigned long val)
{
int BAUD=0, STOP;
char PARITY, CONFIG;
printk ("In IOCTL\n");
printk("command = %d %d val = %d\n", cmd, SET_BAUD, val);
switch (cmd) {
case SET_BAUD:
get_user (BAUD, (int *)val);
printk ("The baud is %d", BAUD);
case SET_PARITY:
case SET_STOP:
case READ_CONFIG:
default:
return -1;
}
return 0;
}
//Open System Call
int NAME_open(struct inode *inode, struct file *filp)
{
printk(KERN_ALERT "\nThis is the Kernel....Open Call.....I have nothing to do.....but YOU ALL HAVE....HAHAHAHA...\n");
return 0;
}
//Close System Call
int NAME_release(struct inode *indoe, struct file *filp)
{
printk(KERN_ALERT "\nThis is the release method of my Character Driver......Bye Dudes......\n");
return 0;
}
//Write Functionality
ssize_t NAME_write(struct file *filp, char __user *Ubuff, size_t count, loff_t *offp)
{
char Kbuff[80];
unsigned long result;
ssize_t retval;
//strcpy(Kbuff,Ubuff);
result=copy_from_user((char *)Kbuff,(char *)Ubuff,count); //get user data
if(result==0)
{
printk(KERN_ALERT "\nMessage from the user......\n>>>> %s <<<<\n",Kbuff);
printk(KERN_ALERT "\n Data Successfully Written.....\n");
retval=count;
return retval;
}
else
{
printk(KERN_ALERT "\n Error Writing Data\n");
retval=-EFAULT;
return retval;
}
}
//read Functionality
ssize_t NAME_read(struct file *filp, char __user *Ubuff, size_t count, loff_t *offp)
{
char Kbuff[]="THis is some date from the kernel to the user....User,ENJOY......";
unsigned long result;
ssize_t retval;
//strcpy(Kbuff,Ubuff);
result=copy_to_user((char *)Ubuff,(char *)Kbuff,sizeof(Kbuff)); //copy to user
if(result==0)
{
//printk("\nMessage from the user......\n>>>> %s <<<<\n");
printk(KERN_ALERT "\n Data Successfully read.....\n");
retval=count;
return retval;
}
else
{
printk(KERN_ALERT"\n Error Writing Data to User\n");
retval=-EFAULT;
return retval;
}
}
int NAME_flush (struct file *filp)
{
printk("\n This is the close function of the file....");
return 0;
}
//Module over ride functions
module_init(CharDevice_init);
module_exit(CharDevice_exit);
header file
#define MAGIC 'x'
#define SET_BAUD _IOW(MAGIC,0, int)
#define SET_PARITY _IOW(MAGIC, 1, char)
#define SET_STOP _IOW(MAGIC, 2, int)
#define READ_CONFIG _IOR(MAGIC, 3, int)
c file
#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <linux/ioctl.h>
#include "myioctl.h"
int main()
{
int FileDesc, Baud=9600;
// char Ubuff[]="THis is the User Buffer......Sending Data to the Kernel....";
// char Kbuff[100];
FileDesc=open("/dev/MyCharDevice",O_RDWR);
if(FileDesc <0)
{
printf("\nError Opening Device\n");
exit(1);
}
ioctl (FileDesc, SET_BAUD, &Baud);
printf("%d %d \n", SET_BAUD, &Baud);
// write(FileDesc,Ubuff,sizeof(Ubuff));
// read(FileDesc,Kbuff,sizeof(Ubuff));
// printf("\n The Data read from the Kernel is\n>>>> %s <<<<\n",Kbuff);
close(FileDesc);
}
I am printing in driver what are the command and value of the argument that print like this
command = 1622004312 1074034688 val = 1622004312
So sent command is equal to the argument I sent. Why this is happening?
I used older IOCTL prototype in my driver.
it should be of this type
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35))
static int my_ioctl(struct inode *i, struct file *f, unsigned int cmd, unsigned long arg)
#else
static long my_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
#endif
In my case against my kernel
static long my_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
is the correct type.

char driver node is not opening

I wrote a simple char driver for my beaglebone kernel
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/uaccess.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/fs.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("mrigendra.chaubey#gmail.com");
#define DEVICE_NAME "experm"
#define CLASS_NAME "exp"
static struct class* myclass = NULL; ///< The device-driver class struct pointer
static struct device* mychardevice = NULL; ///< The device-driver device struct pointer
static int myopen(struct inode *, struct file *);
static int release(struct inode *, struct file *);
static int myioctl(struct inode *, struct file *, unsigned int cmd, unsigned long arg);
static size_t myread(struct file *,char * , size_t, loff_t *);
static size_t mywrite(struct file *,char * , size_t, loff_t *);
static dev_t mydev;
static int myopen(struct inode *nd, struct file *fp)
{
printk(KERN_INFO "myopen\n");
return 0;
}
static int myrelease(struct inode *nd, struct file *fp)
{
printk(KERN_INFO "myrelease\n");
return 0;
}
static int myioctl(struct inode *nd, struct file *fp, unsigned int cmd, unsigned long arg)
{
printk(KERN_INFO "myioctl\n");
return 0;
}
static size_t myread(struct file *fp, char *buf, size_t len, loff_t *ofs)
{
printk(KERN_INFO "myread\n");
return 0;
}
static size_t mywrite(struct file *fp, char *buf, size_t len, loff_t *ofs)
{
printk(KERN_INFO "mywrite\n");
return 0;
}
static struct file_operations fops = {
.open = myopen,
.release = myrelease,
.read = myread,
.write = mywrite,
.unlocked_ioctl = myioctl,
};
static int __init myinit(void)
{
int err;
//extern int alloc_chrdev_region(dev_t *, unsigned minor number, unsigned total, const char *);
err = alloc_chrdev_region(&mydev, 0, 1, "expermdev");
if(err<0)
{
printk(KERN_INFO "major and minor can't be created, err = %d\n", err);
return err;
}
//struct class * class_create ( struct module *owner, const char *name);
myclass = class_create(THIS_MODULE, CLASS_NAME);
if(IS_ERR(myclass))
{
unregister_chrdev(MAJOR(mydev), "expermdev");
printk(KERN_ALERT "Failed to register device class\n");
return PTR_ERR(myclass);
}
//struct device *device_create(struct class *cls, struct device *parent, dev_t devt, void *drvdata, const char *fmt, ...);
//This function can be used by char device classes. A struct device will be created in sysfs, registered to the specified class.
mychardevice = device_create(myclass, NULL, mydev, NULL, "expermdev");
if(IS_ERR(mychardevice))
{
class_destroy(myclass);
unregister_chrdev(MAJOR(mydev), "expermdev");
printk(KERN_ALERT "Failed to create the device\n");
return PTR_ERR(mychardevice);
}
printk(KERN_INFO "my device created correctly\n");
return 0;
}
static void __exit myexit(void)
{
device_destroy(mychardevice, mydev);
class_unregister(myclass);
class_destroy(myclass);
unregister_chrdev(MAJOR(mydev), "expermdev");
printk(KERN_INFO "exited\n");
}
module_init(myinit);
module_exit(myexit);
and app.c file
#include <stdio.h>
#include<fcntl.h>
int main()
{
int fp;
fp = open ("/dev/expermdev", O_RDWR);
if(fp < 0)
printf("file can't be opened\n");
else
printf("file opened\n");
return 0;
}
I am compiling the driver as a module and insmod it, also compiled app.c with the same cross compiler, and put this binary in bin directory. I ran this bin file, but it says
file can't be opened
What am I doing wrong?
Got it. I did not used cdev struture and added fops to it. After that I have to tell kernel about it.
cdev = cdev_alloc();//allocate memory to Char Device structure
cdev->ops = &fops;//link our file operations to the char device
result=cdev_add(cdev,mydev,1);//Notify the kernel abt the new device
also delete this cdev in exit function before unregistering the driver.
In register_chrdev_region we do both things at the same time, but in dynamic allocation of major and minor numbers we have to use cdev to do the rest.

how to write a shell script which communicates with the kernel module

Below is my kernel module,which I tested through C program but now instead of using c application I want to write a shell script which do read and write operation with my kernel module ?
Thanks in advance.
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#define DEVICE_NAME "mydevice"
#define CLASS_NAME "device"
MODULE_LICENSE("GPL");
MODULE_AUTHOR("ABC");
MODULE_DESCRIPTION("A simple Linux character driver");
MODULE_VERSION("0.1");
static int majorNumber;
static char message[256] = {0};
static short size_of_message;
static int numberOpens = 0;
static struct class* character_deviceClass = NULL;
static struct device* character_deviceDevice = NULL;
static int dev_open(struct inode *, struct file *);
static int dev_release(struct inode *, struct file *);
static ssize_t dev_read(struct file *, char *, size_t, loff_t *);
static ssize_t dev_write(struct file *, const char *, size_t, loff_t *);
static DEFINE_MUTEX(devicedev_mutex);
static struct file_operations fops =
{
.open = dev_open,
.read = dev_read,
.write = dev_write,
.release = dev_release,
};
static int __init character_device_init(void){
printk(KERN_INFO "Shell: Initializing the character device LKM\n");
majorNumber = register_chrdev(0, DEVICE_NAME, &fops);
if (majorNumber<0){
printk(KERN_ALERT "character device failed to register a major number\n");
return majorNumber;
}
printk(KERN_INFO "character device: registered correctly with major number %d\n", majorNumber);
character_deviceClass = class_create(THIS_MODULE, CLASS_NAME);
if (IS_ERR(character_deviceClass)){
unregister_chrdev(majorNumber, DEVICE_NAME);
printk(KERN_ALERT "Failed to register device class\n");
return PTR_ERR(character_deviceClass);
}
printk(KERN_INFO "character device: device class registered correctly\n");
character_deviceDevice = device_create(character_deviceClass, NULL, MKDEV(majorNumber, 0), NULL, DEVICE_NAME);
if (IS_ERR(character_deviceDevice)){
class_destroy(character_deviceClass);
unregister_chrdev(majorNumber, DEVICE_NAME);
printk(KERN_ALERT "Failed to create the device\n");
return PTR_ERR(character_deviceDevice);
}
printk(KERN_INFO "character device: device class created correctly\n");
mutex_init(&devicedev_mutex);
return 0;
}
static void __exit character_device_exit(void){
mutex_destroy(&devicedev_mutex);
device_destroy(character_deviceClass, MKDEV(majorNumber, 0));
class_unregister(character_deviceClass);
class_destroy(character_deviceClass);
unregister_chrdev(majorNumber, DEVICE_NAME);
printk(KERN_INFO "character device: Goodbye from the LKM!\n");
}
static int dev_open(struct inode *inodep, struct file *filep){
if(!mutex_trylock(&devicedev_mutex))
{
printk(KERN_ALERT "Character device: Device in use by another process");
return -EBUSY;
}
numberOpens++;
printk(KERN_INFO "character device: Device has been opened %d time(s)\n", numberOpens);
return 0;
}
static ssize_t dev_read(struct file *filep, char *buffer, size_t len, loff_t *offset){
int error_count = 0;
error_count = copy_to_user(buffer, message, size_of_message);
if (error_count==0){
printk(KERN_INFO "character device: Sent %d characters to the user\n", size_of_message);
return (size_of_message=0);
}
else {
printk(KERN_INFO "character device: Failed to send %d characters to the user\n", error_count);
return -EFAULT;
}
}
static ssize_t dev_write(struct file *filep, const char *buffer, size_t len, loff_t *offset){
sprintf(message, "%s(%d letters)", buffer, len);
size_of_message = strlen(message);
printk(KERN_INFO "character device: Received %d characters from the user\n", len);
return len;
}
static int dev_release(struct inode *inodep, struct file *filep){
mutex_unlock(&devicedev_mutex);
printk(KERN_INFO "character device: Device successfully closed\n");
return 0;
}
module_init(character_device_init);
module_exit(character_device_exit);
Let's say that you registered with major number 254 and minor number 1 (the actual code given in your question logs the allocated numbers to dmesg, so check there). If you didn't have udev or similar configured to create a /dev/mydevice for you, you could do so yourself:
mknod /dev/mydevice c 254 1 # substitute the real allocated values
At that point, opening it is the same as with anything else:
# file descriptor number 3 is arbitrary, but the same number needs to be reused later
# don't use 0-2, which are reserved for stdin/stdout/stderr
exec 3<>/dev/mydevice
...and reads and writes are similarly conventional:
echo "This is a write" >&3
read varname <&3 # read until newline from device

Resources