Thread: /dev/mydevice doesn't work!

  1. #1
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300

    /dev/mydevice doesn't work!

    I've gotten a little further into learning about device drivers and made a simple char device module that allocates 4k of contiguous memory and supposedly attaches it for universal use to a device node:
    Code:
    #include <linux/module.h> 
    #include <linux/kernel.h> 
    #include <linux/fs.h>  
    #include <linux/cdev.h>
    #include <linux/types.h>
    
    MODULE_LICENSE("GPL");
    
    #define DEVSIZE 4096
    
    typedef struct {
    	char data[DEVSIZE];
    	struct cdev cdev;
    } OneDevice;
    
    
    
    void cleanup(void); 
    int init(void);
    ssize_t read_onedev(struct file *file, char __user *buf, size_t count, loff_t *pos);
    ssize_t write_onedev(struct file *file, const char __user *buf, size_t count, loff_t *pos);
    //int open_onedev(struct inode *inode, struct file *file);
     
    int Major;
    int Minor = 0;
    OneDevice TestOne;
    char *Current=TestOne.data; /* position pointer */
    
    void cleanup(void) {
    	memset(TestOne.data,0,4096);
    	cdev_del(&TestOne.cdev);
    	printk(KERN_ALERT "Unloaded Test One\n");
    }  
    
    
    int init(void) {
    	int err;
    	dev_t devMM = 0;
    	struct file_operations fops = {
    		.owner = THIS_MODULE,
    		.read = read_onedev,
    		.write = write_onedev,
    //		.open = open_onedev,  
    	};
    
    	printk("Loading Test One...");
    	if ((err=alloc_chrdev_region(&devMM,Minor,1,"testone"))<0) {
    		printk(KERN_WARNING "alloc_chrdev failed!\n");
    		return err; }
    	Major=MAJOR(devMM);
    	printk("registered MAJOR %d MINOR 0\n",Major);		 
    	memset(TestOne.data,0,DEVSIZE);
    	MKDEV(Major,Minor);
    	cdev_init(&TestOne.cdev,&fops);
    	
    	return 0;
    }
    
    
    ssize_t read_onedev(struct file *file, char __user *buf, size_t count, loff_t *pos) {
    	const void *ptr=Current+(long)*pos;
    	if ((long)ptr-(long)TestOne.data>=DEVSIZE) { return 0; }
    	if (DEVSIZE-((long)ptr-(long)TestOne.data)<count) count=DEVSIZE-((long)ptr-(long)TestOne.data);
    	memcpy((void*)buf,ptr,count);
    	*pos+=count;
    	Current=TestOne.data+(long)*pos;
    	return count;	
    }
    
    
    ssize_t write_onedev(struct file *file, const char __user *buf, size_t count, loff_t *pos) {
    	void *ptr=Current+(long)*pos;
    	if (DEVSIZE-((long)ptr-(long)TestOne.data)<count) count=DEVSIZE-((long)ptr-(long)TestOne.data);
    	if (count<=0) { return 0; }
    	memcpy(ptr,(const void*)buf,count);
    	*pos+=count;
    	Current=TestOne.data+(long)*pos;
    	return count;
    }
    
    module_init(init);
    module_exit(cleanup);
    It compiles, loads, and registers fine. Then I get the actual device node number from /var/messages and use it as an argument to this shell script:
    Code:
    #!/bin/bash
    
    if [ -c /dev/testone ] 
    then
    	rm -v -f /dev/testone	
    fi
    mknod /dev/testone c $1 0
    chgrp wheel /dev/testone 
    chmod 664 /dev/testone
    Now, supposedly I should be able to do basic normal things like "cat somefile > /dev/testone" but when I try, I get "bash: /dev/testone: No such device or address" altho stat says it exists and is a character special file.

    So I was just wondering if anyone had done this stuff before and might have an insight.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  2. #2
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    I wasn't actually registering the major number:
    Code:
    cdev_add(&TestOne.cdev,devMM,1);
    There's some work to do tho, I managed to produce my first Oops (Message from syslogd@lhost at Apr 29 16:36:42 ...) by overwriting the 4k, which I guess means just saying "no" ain't good enough.

    Anyway the whole time I have been thinking of a thread by sean from a while ago:
    BSD mmap for shared memory - am I right?

    This idea (ie, a character memory device) seems perfect for that (it's not my idea, nb), since it produces a block which can be accessed by any process via a device node, eg.
    Code:
    cat some.data > /dev/testone
    cp /dev/testone data.copy
    The whole thing (I only used 4k) is right there in kernel space! This could be coded to allocate dynamically.

    In other words, sean could have built his linked list there and freely accessed it from his other processes.

    I would guess that the reason this is not in widespread use is because if everyone wanted to use it that way, ZONE_NORMAL memory would be gone quick. Anyone got a better reason on why not to do this?
    Last edited by MK27; 04-29-2009 at 03:06 PM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. strcmp returning 1...
    By Axel in forum C Programming
    Replies: 12
    Last Post: 09-08-2006, 07:48 PM
  2. getline() don't want to work anymore...
    By mikahell in forum C++ Programming
    Replies: 7
    Last Post: 07-31-2006, 10:50 AM
  3. Why don't the tutorials on this site work on my computer?
    By jsrig88 in forum C++ Programming
    Replies: 3
    Last Post: 05-15-2006, 10:39 PM
  4. fopen();
    By GanglyLamb in forum C Programming
    Replies: 8
    Last Post: 11-03-2002, 12:39 PM
  5. DLL __cdecl doesnt seem to work?
    By Xei in forum C++ Programming
    Replies: 6
    Last Post: 08-21-2002, 04:36 PM

Tags for this Thread