proc 파일 시스템 프로그래밍
글쓴이: sangchu / 작성시간: 월, 2010/06/21 - 12:04오후
지금 proc 파일시스템에 대한 프로그래밍을 하고 있는데, 희한한 부분이 있어서 질문드립니다.
read_num을 생성한 파일시스템의 read_proc으로 등록시켰는데,
읽기를 수행하면 read_num 안의 printk("excute read_num")이 세번이 찍히네요.
세번을 호출한 일이 없는데 어찌 된일인지?
그리고 모듈 프로그래밍할 때 디버깅은 어떻게 하나요? gdb나 strace를 사용할 수 있는건가요?
#include <linux/module.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/kernel.h>
#include <asm/uaccess.h>
#include <linux/ip.h>
#include <linux/in.h>
#include <net/arp.h>
#include <linux/types.h>
#define MODULE_ON 1
#define MODULE_OFF 0
static int num = MODULE_OFF;
static char buf[4*sizeof "123"];
char * inet_ntoa(struct in_addr ina)
{
unsigned char *ucp = (unsigned char *)&ina;
sprintf(buf, "%d.%d.%d.%d",
ucp[0] & 0xff,
ucp[1] & 0xff,
ucp[2] & 0xff,
ucp[3] & 0xff);
return buf;
}
static int my_protocol_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt, struct net_device *orig_dev)
{
unsigned char *p;
int i;
struct iphdr ipheader;
struct in_addr in;
if(skb->pkt_type == PACKET_OTHERHOST || skb->pkt_type == PACKET_LOOPBACK)
{
kfree_skb(skb);
return 1;
}
printk("[Network]\n");
//printk("\n");
p = skb_network_header(skb);
memcpy(&ipheader, p, sizeof(ipheader));
in.s_addr = ipheader.saddr;
printk("src ip : %s\n", inet_ntoa(in));
in.s_addr = ipheader.daddr;
printk("dst ip : %s\n", inet_ntoa(in));
p = skb_mac_header(skb);
printk("[MAC]\n");
printk("dst mac : ");
for(i=0; i<6; i++)
printk("%x:", p[i]);
printk("\n");
printk("src mac : ");
for(; i<12; i++)
printk("%x:", p[i]);
printk("\n");
printk("\n");
kfree_skb(skb);
return 1;
}
static struct packet_type my_packet_type = {
.type = __constant_htons(ETH_P_ALL),
.func = my_protocol_rcv,
};
static int read_num(char * buffer, char ** start, off_t offset, int length)
{
int size = sprintf(buffer, "goodday %d\n", num);
*start = buffer + offset;
size -= offset;
printk("excute read_num\n");
if(size>0)
{
if(size > length)
return length;
else
return size;
}
else
{
if(size > length)
return length;
else
return 0;
}
}
static int write_num(struct file * file, const char * buffer,
unsigned long count, void * data)
{
int val = 0;
char buf[16];
char * endp;
if(count > sizeof(buf))
return -EINVAL;
if(copy_from_user(buf, buffer, count))
return -EFAULT;
val = simple_strtoul(buf, &endp, 10);
if(*endp != '\n')
return -EINVAL;
num = val;
// here dev_add_pack
if(val == MODULE_ON)
dev_add_pack(&my_packet_type);
else if(val == MODULE_OFF)
dev_remove_pack(&my_packet_type);
else
printk("dev_add_pack : 0 , dev_remove_pack : 1\n");
return count;
}
static int num_init(void)
{
struct proc_dir_entry * proc_dir_juhee;
struct proc_dir_entry * proc_wr_num;
proc_dir_juhee = proc_mkdir("juhee", 0);
if(!proc_dir_juhee)
{
printk(KERN_ERR "cannot create /proc/juhee\n");
return -ENOMEM;
}
proc_wr_num = create_proc_entry("num", 0, proc_dir_juhee);
if(!proc_wr_num)
{
printk(KERN_ERR "cannot create /proc/juhee\n");
remove_proc_entry("juhee", 0);
return -ENOMEM;
}
proc_wr_num->read_proc = read_num;
proc_wr_num->write_proc = write_num;
proc_wr_num->data = num;
return 0;
}
static void num_exit(void)
{
remove_proc_entry("juhee/num", 0);
remove_proc_entry("juhee", 0);
}
module_init(num_init);
module_exit(num_exit);
MODULE_LICENSE("GPL");Forums:


코드를 코드블럭으로
코드를 코드블럭으로 감싸주시고 indentation도 넣어주세요. 이대로는 보기가 어려워서 대답할 마음도 가실겁니다;;
저는 커널 디버깅은 보통 printk;;; 로 합니다. 요새는 커널 유틸이 좋아져서 디버거 연결시키는 기능도 분명 있으리라 봅니다. 혹은 qemu나 bochs 등을 통해서 실행하고, gdb를 연결하는 것도 방법이겠지요.
언제나 삽질 - http://tisphie.net/typo/
프로그래밍 언어 개발 - http://langdev.net
언제나 삽질 - http://tisphie.net/typo/
프로그래밍 언어 개발 - http://langdev.net
제가 code lang='c'로
제가 code lang='c'로 감쌌습니다.
혹시 커널버전 몇을
혹시 커널버전 몇을 사용하시나요?
제가 찾아본 커널들은 proc_read_entry에 해당하는 프로토타입이
proc_read_entry ( char *page, char **start, off_t off, int count, int *eof, void *data);처럼 되어서, 전부 읽었다면 *eof = 1 을 설정하게 되어있더군요.
계속 읽었다면 아마 저부분이 문제가 아닐까 합니다.
언제나 삽질 - http://tisphie.net/typo/
프로그래밍 언어 개발 - http://langdev.net
언제나 삽질 - http://tisphie.net/typo/
프로그래밍 언어 개발 - http://langdev.net
댓글 달기