1 memdev.h
#ifndef _MEMDEV_H_
#define _MEMDEV_H_
#include <linux/ioctl.h>
#ifndef MEMDEV_MAJOR
#define MEMDEV_MAJOR 0 //默認爲0,由系統分配主設備號
#endif
#ifndef MEMDEV_NR_DEVS
#define MEMDEV_NR_DEVS 3
#endif
#ifndef MEMDEV_SIZE
#define MEMDEV_SIZE 4096
#endif
typedef struct Mem_Dev {
wait_queue_head_t inq, outq; //阻塞隊列,入對,出對
int rp; //讀的到的位子
int wp; //寫到的位子
char *data;
struct Mem_Dev *next; /* next listitem */
unsigned long size;
unsigned long remain_size;
} Mem_Dev;
2.memdev.c
#ifndef __KERNEL__
#define __KERNEL__#endif
#ifndef MODULE
#define MODULE
#endif
//#include <linux/config.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
//#include <asm/system.h>
#include <asm/uaccess.h>
#include "memdev.h"
MODULE_LICENSE("GPL");
Mem_Dev *mem_devices;
int memdev_major = MEMDEV_MAJOR;
int memdev_open(struct inode *inode, struct file *filp)
{
Mem_Dev *dev;
int num = MINOR(inode->i_rdev);
dev = (Mem_Dev *)filp->private_data;
if (!dev)
{
if (num >= MEMDEV_NR_DEVS)
return -ENODEV;
dev = &mem_devices[num];
filp->private_data = dev;
}
return 0;
}
int memdev_release(struct inode *inode, struct file *filp)
{
printk(KERN_INFO "close module");
return 0;
}
ssize_t memdev_read(struct file *filp, char *buf, size_t count,
loff_t *f_pos)
{
Mem_Dev *dev = filp->private_data;
int pos = *f_pos;
ssize_t ret = 0;
while (dev->rp == dev->wp) //如果讀與寫頭相遇,表示讀完了
{
if (filp->f_flags & O_NONBLOCK) //如果是非阻塞,立即返回
return -EAGAIN;
interruptible_sleep_on(&(dev->inq)); //驅動進入睡眠,進程也即睡眠,進入阻塞隊列等待
}
count = min(count, (ssize_t)(dev->wp - dev->rp));
if (copy_to_user(buf, &(dev->data[pos]), count))
{
ret = -EFAULT;
goto out;
}
*f_pos += count; //當前打開的文件指針位置加 count
dev->rp += count; //驅動的讀頭也加
ret = count;
printk(KERN_INFO "read =%s,count =%d\n",buf,count);
out:
return ret;
}
/*ÎÄŒþÐŽ²Ù×÷*/
ssize_t memdev_write(struct file *filp, const char *buf, size_t count,
loff_t *f_pos)
{
Mem_Dev *dev = filp->private_data;
int pos = *f_pos;
ssize_t ret = -ENOMEM;
/*ÅжÏЎλÖÃÊÇ·ñÓÐЧ*/
if (dev->wp + count > dev->size)
count = (dev->size) - (dev->wp);
/*ŽÓÓû§¿ÕŒäÐŽÈëÊýŸÝ*/
if (copy_from_user(&(dev->data[pos]), buf, count))
{
ret = -EFAULT;
goto out;
}
printk(KERN_INFO "write =%s,count =%d\n",buf,count);
/* »œÐѶÁœø³Ì */
wake_up(&dev->inq);
*f_pos += count;
dev->wp += count;
ret = count;
out:
return ret;
}
/*ÎÄŒþ¶šÎ»*/
loff_t memdev_llseek(struct file *filp, loff_t off, int whence)
{
Mem_Dev *dev = filp->private_data;
loff_t newpos;
switch(whence) {
case 0: /* SEEK_SET */
newpos = off;
break;
case 1: /* SEEK_CUR */
newpos = filp->f_pos + off;
break;
case 2: /* SEEK_END */
newpos = dev->size -1 + off;
break;
default: /* can't happen */
return -EINVAL;
}
if (newpos<0)
return -EINVAL;
filp->f_pos = newpos;
return newpos;
}
/*
* The following wrappers are meant to make things work with 2.0 kernels
*/
struct file_operations memdev_fops = {
llseek: memdev_llseek,
read: memdev_read,
write: memdev_write,
open: memdev_open,
release: memdev_release,
};
/*жÔغ¯Êý*/
void memdev_cleanup_module(void)
{
int i;
unregister_chrdev(memdev_major, "memdev");
/*ÊÍ·ÅÄÚŽæ*/
if (mem_devices)
{
for (i=0; i<MEMDEV_NR_DEVS; i++)
kfree(mem_devices[i].data);
kfree(mem_devices);
}
}
/*ŒÓÔغ¯Êý*/
int memdev_init_module(void)
{
int result, i;
/*×¢²á×Ö·ûÉ豞*/
result = register_chrdev(memdev_major, "memdev", &memdev_fops);
if (result < 0)
{
printk(KERN_WARNING "mem: can't get major %d\n",memdev_major);
return result;
}
if (memdev_major == 0)
memdev_major = result;
mem_devices = kmalloc(MEMDEV_NR_DEVS * sizeof(Mem_Dev), GFP_KERNEL);
if (!mem_devices)
{
result = -ENOMEM;
goto fail;
}
memset(mem_devices, 0, MEMDEV_NR_DEVS * sizeof(Mem_Dev));
for (i=0; i < MEMDEV_NR_DEVS; i++)
{
mem_devices[i].size = MEMDEV_SIZE;
mem_devices[i].data = kmalloc(MEMDEV_SIZE, GFP_KERNEL);
memset(mem_devices[i].data, 0, MEMDEV_SIZE);
init_waitqueue_head(&(mem_devices[i].inq));
}
return 0;
fail:
memdev_cleanup_module();
return result;
}
module_init(memdev_init_module);
module_exit(memdev_cleanup_module);
3. fork.c
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main ()
{
pid_t fpid; //fpid表示fork函數返回的值
int count=0;
fpid=fork();
if (fpid < 0)
printf("error in fork!");
else if (fpid == 0) {
printf("i am the child process, my process id is %d\n",getpid());
count++;
FILE *fp = NULL;
FILE *fp2 = NULL;
char Buf[128];
int i=0;
fp = fopen("/dev/memdev","r+");
if (fp == NULL)
{
printf("Open Dev memdev0 Error!\n");
return -1;
}
while(i<5)
{
i++;
memset(Buf,128,0);
fflush(stdin);
fflush(stdout);
gets(Buf);
fwrite(Buf, sizeof(Buf), 1, fp);
fflush(fp);
}
sleep(5);
fclose(fp);
fclose(fp2);
}
else {
printf("i am the parent process, my process id is %d\n",getpid());
count++;
FILE *fp = NULL;
char Buf[128];
int i=0;
fp = fopen("/dev/memdev","r+");
if (fp == NULL)
{
printf("Open memdev0 Error!\n");
return -1;
}
while(i<5)
{ i++;
memset(Buf,128,0);
fread(Buf, sizeof(Buf), 1, fp);
printf("Read BUF: %s\n",Buf);
}
fclose(fp);
}
printf("count=: %d/n",count);
return 0;
}