http://blog.csdn.net/absurd/archive/2008/11/07/3244482.aspx
手 机内置FLASH容量有限,在磁盘空间不足的情况下,应该提醒用户进行磁盘清理。这个处理在哪里做比较好呢?每次写入数据时由调用者检测显然是不合理的, 因为处理的太多了,何况修改SQLITE等第三方程序也是不明智的,那样会给升级版本带来麻烦。比较好的办法是在文件系统中做处理,最近同事修改了 yaffs2支持磁盘满通知功能。做法如下:
在yaffs_fs.c中:#include <net/sock.h>
#include <linux/netlink.h>
#define DISK_FULL_MSG_SIZE 128
#define NETLINK_DISK_FULL 2
static struct sock yaffs_sock;
在init_yaffs_fs中:
if((yaffs_sock = netlink_kernel_create(NETLINK_DISK_FULL, 1, NULL, THIS_MODULE)) == NULL)
{
printk(KERN_INFO"netlink_kernel_create fail.n");
}
在exit_yaffs_fs中:
if(yaffs_sock != NULL)
{
sock_release(yaffs_sock);
yaffs_sock = NULL;
}
增加两个函数:
void yaffs_notify_space_full(const char partition, const char type, int totalchunk, int freechunk)
{
size_t len = 0;
char scratch = NULL;
struct sk_buff skb = NULL;
totalchunk >>= 10;
freechunk >>= 10;
len = DISK_FULL_MSG_SIZE;
skb = alloc_skb(len, GFP_KERNEL);
if (skb)
{
scratch = skb_put(skb, len);
sprintf(scratch, "diskevent: type=%s total=%dKB free=%dKB partition=%s",
type, totalchunk, freechunk, partition);
NETLINK_CB(skb).dst_group = 1;
netlink_broadcast(yaffs_sock, skb, 0, 1, GFP_KERNEL);
}
return;
}
void yaffs_notify_app_if_space_full(yaffs_Device dev)
{
if (yaffs_sock)
{
const char type = NULL;
int totalchunk = (dev->endBlock - dev->startBlock + 1) dev->nChunksPerBlock dev->nDataBytesPerChunk;
int freechunk = yaffs_GetNumberOfFreeChunks(dev) dev->nDataBytesPerChunk;
if (freechunk < totalchunk / 100)
{
type = "full";
}
else if (freechunk < totalchunk 5 / 100)
{
type = "low";
}
if(type != NULL)
{
yaffs_notify_space_full(dev->name, type, totalchunk, freechunk);
}
}
return;
}
在yaffs_AllocateChunk中:
yaffs_notify_app_if_space_full(dev);
NETLINK是Linux提供的一种用于内核与用户空间进程通信的方式,使用简单,传输效率高,hotplug事件也是通过这种方式通知udev的。
用户空间监听磁盘满事件的实现很简单,我提供了一个示例,有兴趣的朋友可以到这里下载。
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <ctype.h>
#include <sys/un.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/types.h>
#include <linux/netlink.h>
#define DISK_FULL_MSG_SIZE 128
#define NETLINK_DISK_FULL 20
static int create_disk_event_sock(void)
{
int retval = 0;
struct sockaddr_nl snl = {0};
const int buffersize = 64
memset(&snl, 0x00, sizeof(struct sockaddr_nl));
snl.nl_family = AF_NETLINK;
snl.nl_pid = getpid();
snl.nl_groups = 1;
int sock_no = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_DISK_FULL);
if (sock_no < 0)
{
perror("socket");
return -1;
}
setsockopt(sock_no, SOL_SOCKET, SO_RCVBUFFORCE, &buffersize, sizeof(buffersize));
retval = bind(sock_no, (struct sockaddr ) &snl, sizeof(struct sockaddr_nl));
if (retval < 0)
{
perror("bind");
close(sock_no);
return -1;
}
return sock_no;
}
int main(int argc, char argv[])
{
int ret = 0;
int sock_no = create_disk_event_sock();
while(1)
{
char buf[DISK_FULL_MSG_SIZE] = {0};
ret = recv(sock_no, buf, sizeof(buf), 0);
if(ret > 0)
{
printf("%sn", buf);
}
else
{
close(sock_no);
}
}
return 0;
}