# vi devwrite.c
#include
#include
#include
#include
#include
ssize_t dev_write(struct file * filp, const char * buffer,
size_t length, loff_t * offset);
struct file_operations dev_fops = {
write: dev_write,
};
static int major = 0;
int init_module()
{
printk("Loading devwrite module\n");
major = register_chrdev(0, "devwrite", &dev_fops);
if(major < 0) return major;
return 0;
}
void cleanup_module()
{
unregister_chrdev(major, "devwrite");
printk("Unloading devwrite module\n");
}
#define SLOT_NUM 8
char dev_buffer;
int dev_key = 1;
char data_slot[SLOT_NUM];
int full_slot_num = 0;
int empty_slot_num = SLOT_NUM;
int full_slot_pos = 0;
int empty_slot_pos = 0;
void dev_working();
ssize_t dev_write(struct file * filp, const char * buffer,
size_t length, loff_t * offset)
{
char user_buffer;
if(length != 1) return -1;
copy_from_user(&user_buffer, buffer, 1);
if(dev_key == 0) { // ①
if(empty_slot_num <= 0) return -1; // ④ start
empty_slot_num --;
data_slot[empty_slot_pos] = user_buffer;
empty_slot_pos ++;
if(empty_slot_pos == SLOT_NUM)
empty_slot_pos = 0;
full_slot_num ++; // ④ end
return 1;
}
dev_key = 0; // ②
dev_buffer = user_buffer; // ③
dev_working(); // ⑤
return 1;
}
static struct timer_list dev_interrupt;
void dev_interrupt_handler(unsigned long dataptr);
void dev_working()
{
init_timer(&dev_interrupt); // ⑨
dev_interrupt.function = dev_interrupt_handler; // ⑦
dev_interrupt.data = (unsigned long)NULL;
dev_interrupt.expires = jiffies + 1; // ⑥
add_timer(&dev_interrupt); // ⑧
}
void dev_interrupt_handler(unsigned long dataptr)
{
printk("%c\n", dev_buffer);
if(full_slot_num <= 0) {dev_key = 1; return;} // ⑩
full_slot_num --; // ⑪ start
dev_buffer = data_slot[full_slot_pos];
full_slot_pos ++;
if(full_slot_pos == SLOT_NUM) full_slot_pos = 0;
empty_slot_num ++; // ⑪ end
dev_working();
return;
}
디바이스를 사용하고 있지 않으면
디바이스를 사용한다고 표시하고
데이터를 디바이스 버퍼에 쓰고 나간다
cli
디바이스를 사용하고 있지 않으면
디바이스를 사용한다고 표시하고
데이터를 디바이스 버퍼에 쓰고 나간다
sti
unsigned long flags;
local_irq_save(flags);
if(dev_key == 0) {
…
}
dev_key = 0;
dev_buffer = user_buffer;
local_irq_restore(flags);
디바이스를 사용하고 있으면
데이터를 데이터 큐에 넣고 나간다
cli
디바이스를 사용하고 있으면
데이터를 데이터 큐에 넣고 나간다
sti
unsigned long flags;
local_irq_save(flags);
if(dev_key == 0) {
if(empty_slot_num <= 0) {
local_irq_restore(flags);
return -1;
}
empty_slot_num --;
data_slot[empty_slot_pos] = user_buffer;
empty_slot_pos ++;
if(empty_slot_pos == SLOT_NUM)
empty_slot_pos = 0;
full_slot_num ++;
local_irq_restore(flags);
return 1;
}
데이터 큐가 비어 있으면
디바이스를 다 사용했다고 표시하고 나간다
데이터 큐가 비어 있지 않으면
데이터를 하나 꺼내서
디바이스 버퍼에 쓰고 나간다
ssize_t dev_write(struct file * filp, const char * buffer,
size_t length, loff_t * offset)
{
char user_buffer;
unsigned long flags;
if(length != 1) return -1;
copy_from_user(&user_buffer, buffer, 1);
local_irq_save(flags);
if(dev_key == 0) {
if(empty_slot_num <= 0) {
local_irq_restore(flags);
return -1;
}
empty_slot_num --;
data_slot[empty_slot_pos] = user_buffer;
empty_slot_pos ++;
if(empty_slot_pos == SLOT_NUM)
empty_slot_pos = 0;
full_slot_num ++;
local_irq_restore(flags);
return 1;
}
dev_key = 0;
dev_buffer = user_buffer;
local_irq_restore(flags);
dev_working();
return 1;
}
# gcc devwrite.c -c -D__KERNEL__ -DMODULE -I/usr/src/linux-2.4/include
# lsmod
# insmod devwrite.o -f
# lsmod
Module Size Used by Tainted: PF
devwrite 3581 0 (unused)
# cat /proc/devices
Character devices:
...
253 devwrite
...
Block devices:
# mknod /dev/devwrite c 253 0
# ls -l /dev/devwrite
crw-r--r-- 1 root root 253, 0 7월 12 00:03 /dev/devwrite
# vi devwrite-app.c
#include
#include
#include
int main()
{
int fd;
fd = open("/dev/devwrite", O_RDWR);
write(fd, "A", 1);
close(fd);
}
# gcc devwrite-app.c -o devwrite-app
# ./devwrite-app
# rmmod devwrite
# tail /var/log/messages
...
Jul 12 00:16:44 localhost kernel: Loading devwrite module
Jul 12 00:17:00 localhost kernel: A
Jul 12 00:17:13 localhost kernel: Unloading devwrite module
ssize_t dev_write(struct file * filp, const char * buffer,
size_t length, loff_t * offset)
{
char user_buffer;
int i;
if(length != 1) return -1;
copy_from_user(&user_buffer, buffer, 1);
for(i=0;i<600;i++) { // ⑫-⑴
user_buffer = (char)(i%10)+48;
if(dev_key == 0) {
printk("<--1\n"); // ⑬-⑴
if(empty_slot_num <= 0) {
printk("slot is full\n");
while(1) if(empty_slot_num > 0) break; // ⑫-⑵
}
empty_slot_num --;
data_slot[empty_slot_pos] = user_buffer;
empty_slot_pos ++;
if(empty_slot_pos == SLOT_NUM)
empty_slot_pos = 0;
{
int j;
for(j=0;j<0x1000000;j++);
}
printk("<--2\n"); // ⑬-⑵
full_slot_num ++;
continue; // ⑫-⑶
}
dev_key = 0;
dev_buffer = user_buffer;
dev_working();
}
return 1;
}
void dev_interrupt_handler(unsigned long dataptr)
{
printk("%c\n", dev_buffer);
if(full_slot_num <= 0) {
printk("no data\n");
dev_key = 1;
return;
}
full_slot_num --;
dev_buffer = data_slot[full_slot_pos];
full_slot_pos ++;
if(full_slot_pos == SLOT_NUM) full_slot_pos = 0;
empty_slot_num ++;
dev_working();
return;
}
# gcc devwrite.c -c -D__KERNEL__ -DMODULE -I/usr/src/linux-2.4/include
# insmod devwrite.o -f
# ./devwrite-app
# tail /var/log/messages -n 600
...
Jul 12 06:19:46 localhost kernel: <--1 ⒜
Jul 12 06:19:46 localhost kernel: 6
Jul 12 06:19:46 localhost kernel: no data ⒞
Jul 12 06:19:46 localhost kernel: <--2 ⒝
Jul 12 06:19:46 localhost kernel: <--1
Jul 12 06:19:46 localhost kernel: <--2
Jul 12 06:19:46 localhost kernel: <--1
Jul 12 06:19:46 localhost kernel: 8 ⒟
Jul 12 06:19:46 localhost kernel: <--2
Jul 12 06:19:46 localhost kernel: <--1
Jul 12 06:19:46 localhost kernel: 7 ⒠
Jul 12 06:19:46 localhost kernel: <--2
...
# rmmod devwrite
ssize_t dev_write(struct file * filp, const char * buffer,
size_t length, loff_t * offset)
{
char user_buffer;
int i;
unsigned long flags;
if(length != 1) return -1;
copy_from_user(&user_buffer, buffer, 1);
for(i=0;i<600;i++) {
user_buffer = (char)(i%10)+48;
local_irq_save(flags);
if(dev_key == 0) {
printk("<--1\n");
if(empty_slot_num <= 0) {
local_irq_restore(flags);
printk("slot is full\n");
while(1) if(empty_slot_num > 0) break;
}
empty_slot_num --;
data_slot[empty_slot_pos] = user_buffer;
empty_slot_pos ++;
if(empty_slot_pos == SLOT_NUM)
empty_slot_pos = 0;
{
int j;
for(j=0;j<0x1000000;j++);
}
printk("<--2\n");
full_slot_num ++;
local_irq_restore(flags);
continue;
}
dev_key = 0;
dev_buffer = user_buffer;
local_irq_restore(flags);
dev_working();
}
return 1;
}
# gcc devwrite.c -c -D__KERNEL__ -DMODULE -I/usr/src/linux-2.4/include
# insmod devwrite.o -f
# ./devwrite-app
# tail /var/log/messages -n 600
...
Nov 19 18:41:07 localhost kernel: 0
Nov 19 18:41:07 localhost kernel: <--1
Nov 19 18:41:07 localhost kernel: <--2
Nov 19 18:41:07 localhost kernel: 1
Nov 19 18:41:07 localhost kernel: <--1
Nov 19 18:41:07 localhost kernel: <--2
Nov 19 18:41:07 localhost kernel: 2
Nov 19 18:41:07 localhost kernel: <--1
Nov 19 18:41:07 localhost kernel: <--2
Nov 19 18:41:07 localhost kernel: 3
Nov 19 18:41:07 localhost kernel: <--1
Nov 19 18:41:07 localhost kernel: <--2
Nov 19 18:41:07 localhost kernel: 4
Nov 19 18:41:07 localhost kernel: <--1
Nov 19 18:41:07 localhost kernel: <--2
Nov 19 18:41:07 localhost kernel: 5
Nov 19 18:41:07 localhost kernel: <--1
Nov 19 18:41:07 localhost kernel: <--2
Nov 19 18:41:07 localhost kernel: 6
Nov 19 18:41:07 localhost kernel: <--1
Nov 19 18:41:07 localhost kernel: <--2
Nov 19 18:41:07 localhost kernel: 7
Nov 19 18:41:07 localhost kernel: <--1
Nov 19 18:41:07 localhost kernel: <--2
Nov 19 18:41:07 localhost kernel: 8
Nov 19 18:41:07 localhost kernel: <--1
Nov 19 18:41:07 localhost kernel: <--2
Nov 19 18:41:07 localhost kernel: 9
...
이전 글 : ASP.NET 가이드 5. NDoc을 통한 코드 문서화
다음 글 : 리팩토링(1) - 과거와 대결하는 프로그래머의 무기
최신 콘텐츠