Linux Device Driver -- implementation of llseek
My "llseek" got killed when I ran it my application file CDD2app.c below.
Not sure what I need to look at next, any help would be appreciated. If
lseek is commented out, it's OK. So, must be something wrong in llseek.
Thanks,
Linux Kernel: 3.10
Linux: Ubuntu 12.04 LTS
Errors:
Killed make: ... [run] Error 137
CDD2.c file
//================================
static loff_t CDD_llseek (struct file *file, loff_t CDDoffset, int whence)
{
int len;
struct CDD_dev *thisCDD=file->private_data;
loff_t newoffset, curroffset;
curroffset = file->f_pos;
len = thisCDD->counter;
switch(whence) {
case SEEK_SET: // CDDoffset can be 0 or +number
curroffset = 0;
if (CDDoffset < 0) // Cannot seek past beginning of data
return -EINVAL;
if (CDDoffset > CDD_BUFSIZE) // Do Not Support Sparse files.
return -EINVAL; // Cannot Seek Past EOF
if (CDDoffset > len) // Cannot Seek past actually used.
return -EINVAL;
newoffset = curroffset + CDDoffset;
break;
case SEEK_CUR: // CDDoffset can be +/- number
if (CDDoffset < 0) { // CDDoffset is -number
if ((CDDoffset + curroffset) < 0) // new offset cannot be < 0;
return -EINVAL;
}
else { // CDDoffset is +ve
if ((CDDoffset + curroffset) > CDD_BUFSIZE) // No Sparse files.
return -EINVAL;
if ((CDDoffset + curroffset) > len) // Cannot seek past actual use
return -EINVAL;
}
newoffset = curroffset + CDDoffset;
break;
case SEEK_END: // CDDoffset can be 0 or -number
if (CDDoffset > 0) // No Sparse files.
return -EINVAL;
if ((CDDoffset + len) < 0) // new offset cannot be < 0;
return -EINVAL;
newoffset = len + CDDoffset;
break;
default:
return -EINVAL;
}
file->f_pos = newoffset;
return newoffset;
}
static struct file_operations CDD_fops =
{
owner: THIS_MODULE, // struct module *owner
open: CDD_open, // open method
read: CDD_read, // read method
write: CDD_write, // write method
llseek: CDD_llseek, // llseek method
release: CDD_release // release method
};
static int CDD_init(void)
{
int i, errno;
dev_t devno;
struct cdev *cdevp;
struct CDD_dev *thisCDD;
CDDmajor = CDDparm;
if (CDDmajor) {
// Step 1a of 2: create/populate device numbers
devno = MKDEV(CDDmajor, CDDMINOR);
// Step 1b of 2: request/reserve Major Number from Kernel
i = register_chrdev_region(devno,CDDNUMDEVS,"CDD16");
if (i < 0) { printk(KERN_ALERT "Error (%d) adding CDD", i); return i;}
}
else {
// Step 1c of 2: Request a Major Number Dynamically.
i = alloc_chrdev_region(&devno, CDDMINOR, CDDNUMDEVS, "CDD16");
if (i < 0) { printk(KERN_ALERT "Error (%d) adding CDD", i); return i;}
CDDmajor = MAJOR(devno);
printk(KERN_ALERT "kernel assigned major number: %d to CDD\n", CDDmajor);
}
// initialize and allocate the devices
thisCDD=&CDD_devdata;
thisCDD->CDD_value=vmalloc(16);
cdevp=&(thisCDD->CDD_cdev);
// Make a Device number here
devno = MKDEV(CDDmajor,i);
// start initializing our devices
sema_init(&(thisCDD->CDD_sem),1);
thisCDD->CDD_devno = devno;
// Step 2a of 2: initialize cdev struct
cdev_init(cdevp, &CDD_fops);
// Step 2b of 2: register device with kernel
cdevp->owner = THIS_MODULE;
cdevp->ops = &CDD_fops;
errno = cdev_add(cdevp, devno, CDDNUMDEVS);
if (errno)
{
printk(KERN_ALERT "Error (%d) adding %s(%d\n",errno,"CDD16",i);
return errno;
}
return 0;
}
static void CDD_exit(void)
{
struct cdev *cdevp;
struct CDD_dev *thisCDD;
dev_t devno;
// initialize and allocate the devices
thisCDD=&CDD_devdata;
vfree(thisCDD->CDD_value);
cdevp=&(thisCDD->CDD_cdev);
// Step 1 of 2: unregister device with kernel
cdev_del(cdevp);
// Step 2a of 2: create/populate device numbers
devno = MKDEV(CDDmajor, CDDMINOR);
// Step 2b of 2: Release request/reserve of Major Number from Kernel
unregister_chrdev_region(devno, CDDNUMDEVS);
if (CDDmajor != CDDparm)
printk(KERN_ALERT "kernel unassigned major number: %d from CDD\n", CDDmajor);
}
module_init(CDD_init);
module_exit(CDD_exit);
//=============================
//CDD2app.c file
/////////////////////
/* CDD2app.c */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
main() {
int fd, len, wlen;
char str[128] = "GoodDay!";
int num, rnum;
// open
if((fd = open("/dev/CDD16/CDD2_a", O_RDWR | O_APPEND)) == -1) {
fprintf(stderr,"ERR:on open():%s\n",strerror(errno));
exit(0);
}
// write
wlen = strlen(str);
if ((len = write(fd, str, wlen)) == -1) {
fprintf(stderr,"ERR:on write():%s\n",strerror(errno));
exit(1);
}
if (lseek(fd, -999, SEEK_SET) < 0) // -ve test
{
fprintf(stderr, "ERR: on lseek():%s\n", strerror(errno));
}
close(fd);
}
///////////////////////////////////
No comments:
Post a Comment