之前以為在核心中不能建立檔案,其實不是這樣子的,隻要檔案系統跑起來之後就可以像在使用者空間一樣操作檔案.
使用者空間 核心
open() sys_open(), filp_open()
close() sys_close(), filp_close()
read() sys_read(), filp_read()
write() sys_write(), filp_write()
----------------------------------------------------
在核心子產品中有時會用不了 sys_xxxx, 這時用 filp_xxxx 對應的函數就行了, 在子產品中使用 sys_xxxx 還有問題, 還沒有找到原因.
在 /tmp 中建立檔案 aa
struct file *filep;
filep=filp_open("/tmp/aa",O_CREAT | O_RDWR,0);
if(IS_ERR(filep))
return -1;
filp_close(filep,0);
return 0;
========================================
sys_open 的使用方法:
#include <linux/fs.h>
......
u8 Buff[50];
int fd;
memset(Buff, 0x00, sizeof(Buff));
mm_segment_t old_fs = get_fs();
set_fs(KERNEL_DS);
fd = sys_open("/etc/Info", O_RDONLY, 0);
if(fd>=0)
{
sys_read(fd, Buff, 50);
printk("string: %s/n", Buff);
sys_close(fd);
}
set_fs(old_fs);
下面 open 使用的一些參數:
O_ACCMODE <0003>;: 讀寫檔案操作時,用于取出flag的低2位。
O_RDONLY<00>;: 隻讀打開
O_WRONLY<01>;: 隻寫打開
O_RDWR<02>;: 讀寫打開
O_CREAT<0100>;: 檔案不存在則建立,需要mode_t,not fcntl
O_EXCL<0200>;: 如果同時指定了O_CREAT,而檔案已經存在,則出錯, not fcntl
O_NOCTTY<0400>;: 如果pathname指終端裝置,則不将此裝置配置設定作為此程序的控制終端。not fcntl O_TRUNC<01000>;: 如果此檔案存在,而且為隻讀或隻寫成功打開,則将其長度截短為0。not fcntl
O_APPEND<02000>;: 每次寫時都加到檔案的尾端
O_NONBLOCK<04000>;: 如果p a t h n a m e指的是一個F I F O、一個塊特殊檔案或一個字元特殊檔案,則此選擇項為此檔案的本次打開操作和後續的I / O操作設定非阻塞方式。
O_NDELAY;;
O_SYNC<010000>;: 使每次write都等到實體I/O操作完成。
FASYNC<020000>;: 相容BSD的fcntl同步操作
O_DIRECT<040000>;: 直接磁盤操作辨別
O_LARGEFILE<0100000>;: 大檔案辨別
O_DIRECTORY<0200000>;: 必須是目錄
O_NOFOLLOW<0400000>;: 不擷取連接配接檔案
O_NOATIME<01000000>;: 暫無
當新建立一個檔案時,需要指定mode 參數,以下說明的格式如宏定義名稱<實際常數值>;: 描述。
S_IRWXU<00700>;:檔案擁有者有讀寫執行權限
S_IRUSR (S_IREAD)<00400>;:檔案擁有者僅有讀權限
S_IWUSR (S_IWRITE)<00200>;:檔案擁有者僅有寫權限
S_IXUSR (S_IEXEC)<00100>;:檔案擁有者僅有執行權限
S_IRWXG<00070>;:組使用者有讀寫執行權限
S_IRGRP<00040>;:組使用者僅有讀權限
S_IWGRP<00020>;:組使用者僅有寫權限
S_IXGRP<00010>;:組使用者僅有執行權限
S_IRWXO<00007>;:其他使用者有讀寫執行權限
S_IROTH<00004>;:其他使用者僅有讀權限
S_IWOTH<00002>;:其他使用者僅有寫權限
S_IXOTH<00001>;:其他使用者僅有執行權限
Linux驅動程式設計書籍大多數都是介紹怎樣使用者态下怎麼通路硬體裝置,由于項目的需要,本人做了核心态下通路裝置檔案的方法,現在把程式拿出來和大家分享一下,希望對剛入門的朋友有所幫助。
在我的《核心子產品調用驅動》中給出了簡單的字元裝置檔案程式,可以作為本文的驅動對象,在此,我就不多介紹了。調用驅動程式的子產品如下:
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/stat.h>
#include <asm/unistd.h>
#include <asm/uaccess.h>
#include <linux/types.h>
#include <linux/ioctl.h>
#include "chardev.h"
MODULE_LICENSE("GPL");
//#define __KERNEL_SYSCALLS__
#define bao "/dev/baovar"
static char buf1[20];
static char buf2[20];
static int __init testmod_init(void)
{
mm_segment_t old_fs;
ssize_t result;
ssize_t ret;
sprintf(buf1,"%s","baoqunmin");
struct file *file=NULL;
file=filp_open(bao,O_RDWR,0);
if(IS_ERR(file)) goto fail0;
old_fs=get_fs();
set_fs(get_ds());
ret=file->f_op->write(file,buf1,sizeof(buf1),&file->f_pos);
result=file->f_op->read(file,buf2,sizeof(buf2),&file->f_pos);
if(result>=0){buf2[20]='/n';printk("buf2-->%s/n",buf2);}
else printk("failed/n");
result=file->f_op->ioctl(file,buf2,sizeof(buf2),&file->f_pos);
set_fs(old_fs);
filp_close(file,NULL);
printk("file loaded/n");
return 0;
fail0:{filp_close(file,NULL);printk("load failed/n");}
return 1;
}
static void __exit testmod_cleanup(void)
printk("module exit....................................................../n");
module_init(testmod_init);
module_exit(testmod_cleanup);
以上是完整的程式,直接可以編譯運作。
#include "chardev.h"頭檔案定義如下,此頭檔案也必須在驅動中包含!
#define BAO_IOCTL 't'
#define IOCTL_READ _IOR(BAO_IOCTL, 0, int)
#define IOCTL_WRITE _IOW(BAO_IOCTL, 1, int)
#define BAO_IOCTL_MAXNR 1
以下給出了我的Makefile檔案:
CC=gcc
MODCFLAGS := -Wall -DMODULE -D__KERNEL__ -DLINUX -I/usr/src/linux-2.4.20-8/include
test.o :test.c
$(CC) $(MODCFLAGS) -c test.c
echo insmod test.o to turn it on
echo rmmod test to turn it off
echo
1.先加載裝置驅動,我的裝置檔案為bao,
2.再make以上檔案
3./sbin/insmod test.o加載子產品
4.dmesg 檢視運作結果
5./sbin/rmmod test
6.解除安裝加載的驅動
我在Linux red hat 9.0下成功運作
我實作的隻是在子產品間對驅動程式的調用,可以說是這是一個最簡單的例子。
希望大家能有所收獲!