cli
디바이스를 사용하고 있지 않으면
디바이스를 사용한다고 표시하고
디바이스에 데이터 읽기를 요청하고
sti
while(1) {
if(dev_working_done mmgt; 0) {
dev_working_done --;
break;
}
}
dev_working_done ++;
while(1) {
if(dev_working_done mmgt; 0) {
dev_working_done --;
break;
}
interruptible_sleep_on(&wait_queue_in);
}
dev_working_done ++;
wake_up_interruptible(&wait_queue_in);
while(1) {
if(dev_working_done mmgt; 0) {
dev_working_done --;
break;
}
interruptible_sleep_on(&wait_queue);
}
dev_working_done ++;
wake_up_interruptible(&wait_queue);
while(1) {
if(dev_working_done mmgt; 0) {
dev_working_done --;
break;
}
dev_working_done ++;
wake_up_interruptible(&wait_queue);
interruptible_sleep_on(&wait_queue);
}
while(1) {
if(dev_working_done mmgt; 0) {
dev_working_done --;
break;
}
wait_event_interruptible(wait_queue_in, (dev_working_done mmgt; 0));
}
cli
디바이스를 사용하고 있으면
디바이스의 사용이 끝나기를 기다린다
sti
while(1) {
local_irq_save(flags);
if(dev_key mmgt; 0) { ------ ①
dev_key --;
break;
}
local_irq_restore(flags);
}
DEV_READ_COMMAND;
local_irq_restore(flags);
local_irq_save(flags);
dev_key ++;
local_irq_restore(flags);
while(1) {
local_irq_save(flags);
if(dev_key mmgt; 0) {
dev_key --;
break;
}
local_irq_restore(flags);
wait_event_interruptible(wait_queue_out, (dev_key mmgt; 0));
}
DEV_READ_COMMAND;
local_irq_restore(flags);
local_irq_save(flags);
dev_key ++;
local_irq_restore(flags);
wake_up_interruptible(&wait_queue_out);
# vi devread-sync.c
#include mmlt;linux/kernel.hmmgt;
#include mmlt;linux/module.hmmgt;
#include mmlt;linux/fs.hmmgt;
#include mmlt;linux/kdev_t.hmmgt;
#include mmlt;asm/uaccess.hmmgt;
ssize_t dev_read(struct file * filp, char * buffer,
size_t length, loff_t * offset);
struct file_operations dev_fops = {
read: dev_read,
};
static int major = 0;
int init_module()
{
printk("Loading devread-sync module\n");
major = register_chrdev(0, "devread-sync", &dev_fops);
if(major mmlt; 0) return major;
return 0;
}
void cleanup_module()
{
unregister_chrdev(major, "devread-sync");
printk("Unloading devread-sync module\n");
}
#define SLOT_NUM 8
char dev_buffer = 0;
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();
int dev_working_done = 0;
#define DEV_READ_COMMAND
ssize_t dev_read(struct file * filp, char * buffer,
size_t length, loff_t * offset)
{
char user_buffer;
unsigned long flags;
if(length != 1) return -1;
while(1) {
local_irq_save(flags);
if(dev_key mmgt; 0) {
dev_key --;
break;
}
local_irq_restore(flags);
}
DEV_READ_COMMAND;
local_irq_restore(flags);
dev_working();
while(1) {
if(dev_working_done mmgt; 0) {
dev_working_done --;
break;
}
}
full_slot_num --;
user_buffer = data_slot[full_slot_pos];
full_slot_pos ++;
if(full_slot_pos == SLOT_NUM) full_slot_pos = 0;
empty_slot_num ++;
local_irq_save(flags);
dev_key ++;
local_irq_restore(flags);
copy_to_user(buffer, &user_buffer, 1);
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("%d\n", dev_buffer);
dev_buffer ++;
top_half:
empty_slot_num --;
data_slot[empty_slot_pos] = dev_buffer;
empty_slot_pos ++;
if(empty_slot_pos == SLOT_NUM) empty_slot_pos = 0;
full_slot_num ++;
bottom_half:
dev_working_done ++;
return;
}
# gcc devread-sync.c -c -D__KERNEL__ -DMODULE -I/usr/src/linux-2.4/include
# lsmod
# insmod devread-sync.o -f
# lsmod
Module Size Used by Tainted: PF
devread-sync 3004 0 (unused)
...
# cat /proc/devices
Character devices:
...
254 devread-sync
Block devices:
...
# mknod /dev/devread-sync c 254 0
# ls -l /dev/devread-sync
crw-r--r-- 1 root root 254, 0 12월 6 07:46 /dev/devread-sync
# vi devread-sync-app.c
#include mmlt;sys/types.hmmgt;
#include mmlt;sys/stat.hmmgt;
#include mmlt;fcntl.hmmgt;
int main()
{
int fd;
char buffer;
int i;
fd = open("/dev/devread-sync", O_RDWR);
for(i=0;immlt;100;i++) {
read(fd, &buffer, 1);
printf("pid %d: %d\n", getpid(), buffer);
}
close(fd);
}
# gcc devread-sync-app.c -o devread-sync-app
# ./devread-sync-app
pid 1435: 1
pid 1435: 2
pid 1435: 3
pid 1435: 4
pid 1435: 5
...
# rmmod devread-sync
DECLARE_WAIT_QUEUE_HEAD(wait_queue_in);
ssize_t dev_read(struct file * filp, char * buffer,
size_t length, loff_t * offset)
{
…
while(1) {
if(dev_working_done mmgt; 0) { // ②
dev_working_done --;
break;
}
printk("sleep on wait queue in start\n");
interruptible_sleep_on(&wait_queue_in); // ③
printk("sleep on wait queue in end\n");
}
…
}
void dev_interrupt_handler(unsigned long dataptr)
{
…
bottom_half:
dev_working_done ++;
printk("wake up wait queue in\n");
wake_up_interruptible(&wait_queue_in); // ④
return;
}
# gcc devread-sync.c -c -D__KERNEL__ -DMODULE -I/usr/src/linux-2.4/include
# insmod devread-sync.o -f
# ./devread-sync-app
pid 6547: 1
pid 6547: 2
pid 6547: 3
# rmmod devread-sync
ssize_t dev_read(struct file * filp, char * buffer,
size_t length, loff_t * offset)
{
…
while(1) {
if(dev_working_done mmgt; 0) {
dev_working_done --;
break;
}
printk("sleep on wait queue in start\n");
wait_event_interruptible(wait_queue_in, (dev_working_donemmgt;0));
printk("sleep on wait queue in end\n");
}
…
}
# gcc devread-sync.c -c -D__KERNEL__ -DMODULE -I/usr/src/linux-2.4/include
# insmod devread-sync.o -f
# ./devread-sync-app
pid 1580: 1
pid 1580: 2
pid 1580: 3
pid 1580: 4
pid 1580: 5
...
# rmmod devread-sync
DECLARE_WAIT_QUEUE_HEAD(wait_queue_in);
DECLARE_WAIT_QUEUE_HEAD(wait_queue_out);
ssize_t dev_read(struct file * filp, char * buffer,
size_t length, loff_t * offset)
{
…
while(1) {
local_irq_save(flags);
if(dev_key mmgt; 0) {
dev_key --;
break;
}
local_irq_restore(flags);
printk("sleep on wait queue out start\n");
wait_event_interruptible(wait_queue_out, (dev_keymmgt;0));
printk("sleep on wait queue out start\n");
}
DEV_READ_COMMAND;
local_irq_restore(flags);
…
local_irq_save(flags);
dev_key ++;
local_irq_restore(flags);
printk("wake up wait queue out\n");
wake_up_interruptible(&wait_queue_out);
…
}
# gcc devread-sync.c -c -D__KERNEL__ -DMODULE -I/usr/src/linux-2.4/include
# insmod devread-sync.o -f
# vi devread-sync-app-sh
#!/bin/sh
./devread-sync-app &
./devread-sync-app &
./devread-sync-app &
./devread-sync-app &
./devread-sync-app &
./devread-sync-app &
# chmod u+x devread-sync-app-sh
# ./devread-sync-app-sh
...
pid 6601: 55
pid 6602: 57
pid 6601: 56
pid 6602: 58
...
# rmmod devread-sync
최신 콘텐츠