操作系統(tǒng)課的實驗癌幕,proc文件系統(tǒng)踩坑,及解決記錄
老師給的代碼
//proc.c
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
static struct proc_dir_entry *mydir;
static struct proc_dir_entry *pfile;
static char msg[255];
static int myproc_read(char *page, char **start, off_t off, int count, int *eof, void *data)
{
int len = strlen(msg);
if (off >= len)
return 0;
if (count > len - off)
count = len - off;
memcpy(page + off, msg + off, count);
return off + count;
}
static int myproc_write(struct file *file, const char __user *buffer, unsigned long count, void *data)
{
unsigned long count2 = count;
if (count2 >= sizeof(msg))
count2 = sizeof(msg) - 1;
if (copy_from_user(msg, buffer, count2))
return -EFAULT;
msg[count2] = '\0';
return count;
}
static int __init myproc_init(void)
{
mydir = proc_mkdir("mydir", NULL);
if (!mydir) {
printk(KERN_ERR "Can't create /proc/mydir\n");
return -1;
}
pfile = create_proc_entry("pool", 0666, mydir);
if (!pfile) {
printk(KERN_ERR "Can't create /proc/mydir/pool\n");
remove_proc_entry("mydir", NULL);
return -1;
}
pfile->read_proc = myproc_read;
pfile->write_proc = myproc_write;
return 0;
}
static void __exit myproc_exit(void)
{
remove_proc_entry("pool", mydir);
remove_proc_entry("mydir", NULL);
}
module_init(myproc_init);
module_exit(myproc_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Lilan");
問題
當我按照實驗指導使用make指令編譯時出現(xiàn)了implicit declaration of function ‘copy_from_user’
,implicit declaration of function ‘create_proc_entry’
和dereferencing pointer to incomplete type ‘struct proc_dir_entry’
三個錯誤悼枢。
解決
implicit declaration of function ‘copy_from_user’
錯誤位置
if (copy_from_user(msg, buffer, count2))
解決過程
打開編譯時所依賴的庫(我這是 /lib/modules/5.3.0-53-generic/build/include)找到asm文件夾下的uaccess.h后發(fā)現(xiàn)里面的copy_from_user
變動成了raw_copy_from_user()
參數(shù)沒有變動犀概,修改函數(shù)名后問題就解決了
implicit declaration of function ‘create_proc_entry’
錯誤位置
pfile = create_proc_entry("pool", 0666, mydir);
if (!pfile) {
printk(KERN_ERR "Can't create /proc/mydir/pool\n");
remove_proc_entry("mydir", NULL);
return -1;
}
pfile->read_proc = myproc_read;
pfile->write_proc = myproc_write;
return 0;
解決過程
按和上面一樣的方法找到linux文件夾下的proc_fs.h,查看后發(fā)現(xiàn)找不到create_proc_entry
這個函數(shù)挂滓,不過找到了一個名為proc_create
的函數(shù)苦银,于是猜測這是否就create_proc_entry
的替代。
查看函數(shù)后蒙了赶站,原本的函數(shù)只有三個參數(shù)幔虏,而這個函數(shù)居然有四個參數(shù)。
于是面向百度編程贝椿,搜索一番后果然猜想沒錯想括,確實是由proc_create
替代了之前的create_proc_entry
,并且博客上還寫出了使用方法。參考的博客
根據(jù)博客上所寫烙博,第四個參數(shù)是用來指定read和write函數(shù)用的結(jié)構(gòu)體,那么dereferencing pointer to incomplete type ‘struct proc_dir_entry’
這個錯誤也就明白了瑟蜈,因為通過定義結(jié)構(gòu)體來指定read和write函數(shù)了,所以原本用來指定的struct proc_dir_entry
結(jié)構(gòu)體中自然就已經(jīng)沒有了這兩個指針渣窜。
修改后
static struct file_operations my_ops={//新增的結(jié)構(gòu)體
.read=myproc_read,
.write=myproc_write,
.owner=THIS_MODULE,
};
.
.
.
pfile = proc_create("pool", 0666, mydir,&my_ops);//在這里新增了結(jié)構(gòu)體的地址
if (!pfile) {
printk(KERN_ERR "Can't create /proc/mydir/pool\n");
remove_proc_entry("mydir", NULL);
return -1;
}
//兩個pfile->都刪除
return 0;
然后
本以為這樣就解決了铺根,然后再次make,這下好了myproc_read
和myproc_write
也出現(xiàn)了implicit declaration of function 的錯誤(老師啊乔宿,不帶這么坑學生的……)
解決
于是我打開找到file_operations這個結(jié)構(gòu)體,找到了里面read和write函數(shù)的結(jié)構(gòu)一看
//file_operations中的
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
//我的
int myproc_read(char *page, char **start, off_t off, int count, int *eof, void *data)
int myproc_write(struct file *file, const char __user *buffer, unsigned long count, void *data)
這尼瑪相差也太大了位迂,唉看來是要把老師給的代碼來一個大整改了啊(吐血)
修改的過程我就不描述了,這里貼上改好的代碼,如果未來恰好有學弟學妹的也碰上了同樣的實驗,遇見了同樣的問題,希望能有所幫助囤官。因為實驗報告要求代碼詳細注釋冬阳,注釋我也就保留不刪了(注釋是我自己的理解有錯別噴,哈哈)党饮。
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
static struct proc_dir_entry *mydir;
static struct proc_dir_entry *pfile;
static ssize_t myproc_write(struct file *file, const char __user *buff, size_t len, loff_t *pos);
static ssize_t myproc_read(struct file *filp,char __user *buff,size_t len, loff_t *pos);
static char msg[255];
static struct file_operations my_ops={//定義file_operations的結(jié)構(gòu)體指定read和write函數(shù)
.read=myproc_read,
.write=myproc_write,
.owner=THIS_MODULE,
};
static ssize_t myproc_read(struct file *filp,char __user *buff,size_t count, loff_t *pos)
{
unsigned int len=strlen(msg);//得到內(nèi)核空間大小
unsigned long p = *pos;//獲取偏移量
if(p>=len)//如果偏移超過了空間容量則返回0
return 0;
if (count > len-p)//如果用戶讀取大于內(nèi)核空間肝陪,修正為全部讀出
count = len-p;
if(raw_copy_to_user(buff+p,msg+p, count))//將內(nèi)核空間內(nèi)容復制進用戶空間
return -EFAULT;//如果失敗返回錯誤碼
*pos+=count;//偏移量修正
printk("read pos:%ld,count:%ld\n",p,count);
return count;//返回讀取長度
}
static ssize_t myproc_write(struct file *file, const char __user *buff, size_t len, loff_t *pos)
{
unsigned long len2 = len;
if (len2>=sizeof(msg))//如果寫入的內(nèi)容超出內(nèi)核空間容量
len2=sizeof(msg)-1;//只保留可存儲部分
if (raw_copy_from_user(msg, buff, len2))//將緩存的內(nèi)容寫入內(nèi)核空間
return -EFAULT;//返回錯誤碼
msg[len2] = '\0';//結(jié)束標識符
return len;//返回寫入長度
}
static int __init myproc_init(void)
{
mydir = proc_mkdir("mydir", NULL);//創(chuàng)建proc文件夾mydir
if (!mydir) {
printk(KERN_ERR "Can't create /proc/mydir\n");//創(chuàng)建失敗系統(tǒng)報錯并結(jié)束模塊
return -1;
}
pfile = proc_create("pool", 0666, mydir,&my_ops);//創(chuàng)建proc文件pool并賦予用戶讀寫權(quán)限,并指定讀寫方法
if (!pfile) {
printk(KERN_ERR "Can't create /proc/mydir/pool\n");
remove_proc_entry("mydir", NULL);
return -1;//如果創(chuàng)建失敗刪除mydir文件夾并報錯結(jié)束模塊
}
return 0;
}
static void __exit myproc_exit(void)
{
remove_proc_entry("pool", mydir);//刪除mydir文件夾中的pool文件
remove_proc_entry("mydir", NULL);//刪除mydir文件夾
}
module_init(myproc_init);//模塊初始化調(diào)用myproc_init函數(shù)
module_exit(myproc_exit);//模塊卸載時調(diào)用myproc_exit函數(shù)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Rainc");