Monday, May 25, 2009

I/O stream buffer

最近作项目时觉得写大数据量写入时性能不行.  于是研究了 I/O stream buffer.

iso c中规定了standard io stream interface.  这部分实现在 glibc 中,于是研究了一下.
stream buffer 的分配不在fopen里.  是在第一次对文件写的时候. 大小为fstat得到的st_blksize(见_IO_file_doallocate).

fwrite逻辑为:  先往stream buffer 填, 如果填满了以后还有数据要写,则先flush一下, 然后判断剩余数据大小,   如果大于buffer 大小,  则以buffer 大小为倍数,  把整倍数的数据直接使用write写入.   最后剩下的数据才写入到 buffer  里( 见_IO_new_file_xsputn).

故如果以64k为单位写入ext3文件系统(st_blksize=4k), 则每次写入都对应两次write操作.  一次为4k , 一次为 60k.

android平台初步分析

内核打印:

Uncompressing Linux.......................................................................................... done, booting the kernel.
Linux version 2.6.29-00135-ga4ae495 (dybbuk@localhost.localdomain) (gcc version 4.3.1 (GCC) ) #1 Mon May 18 22:01:19 CST 2009
CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=00093177
CPU: VIVT data cache, VIVT instruction cache
Machine: Goldfish
Memory policy: ECC disabled, Data cache writeback
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 24384
Kernel command line: qemu=1 console=ttyS0 androidboot.console=ttyS1 android.checkjni=1 android.qemud=ttyS2 android.ndns=1
Unknown boot option `androidboot.console=ttyS1': ignoring
Unknown boot option `android.checkjni=1': ignoring
Unknown boot option `android.qemud=ttyS2': ignoring
Unknown boot option `android.ndns=1': ignoring
PID hash table entries: 512 (order: 9, 2048 bytes)
Console: colour dummy device 80x30
Dentry cache hash table entries: 16384 (order: 4, 65536 bytes)
Inode-cache hash table entries: 8192 (order: 3, 32768 bytes)
Memory: 96MB = 96MB total
Memory: 93880KB available (2528K code, 671K data, 108K init)
Calibrating delay loop... 183.91 BogoMIPS (lpj=919552)
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
net_namespace: 520 bytes
NET: Registered protocol family 16
bio: create slab <bio-0> at 0
NET: Registered protocol family 2
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
TCP established hash table entries: 4096 (order: 3, 32768 bytes)
TCP bind hash table entries: 4096 (order: 2, 16384 bytes)
TCP: Hash tables configured (established 4096 bind 4096)
TCP reno registered
NET: Registered protocol family 1
checking if image is initramfs... it is
Freeing initrd memory: 140K
goldfish_new_pdev goldfish_interrupt_controller at ff000000 irq -1
goldfish_new_pdev goldfish_device_bus at ff001000 irq 1
goldfish_new_pdev goldfish_timer at ff003000 irq 3
goldfish_new_pdev goldfish_rtc at ff010000 irq 10
goldfish_new_pdev goldfish_tty at ff002000 irq 4
goldfish_new_pdev goldfish_tty at ff011000 irq 11
goldfish_new_pdev goldfish_tty at ff012000 irq 12
goldfish_new_pdev smc91x at ff013000 irq 13
goldfish_new_pdev goldfish_fb at ff014000 irq 14
goldfish_new_pdev goldfish_audio at ff004000 irq 15
goldfish_new_pdev goldfish_memlog at ff006000 irq -1
goldfish_new_pdev goldfish-battery at ff015000 irq 16
goldfish_new_pdev goldfish_events at ff016000 irq 17
goldfish_new_pdev goldfish_nand at ff017000 irq -1
goldfish_new_pdev goldfish-switch at ff018000 irq 18
goldfish_new_pdev goldfish-switch at ff019000 irq 19
goldfish_pdev_worker registered goldfish-switch
goldfish_pdev_worker registered goldfish-switch
goldfish_pdev_worker registered goldfish_nand
goldfish_pdev_worker registered goldfish_events
goldfish_pdev_worker registered goldfish-battery
goldfish_pdev_worker registered goldfish_memlog
goldfish_audio_probe
goldfish_pdev_worker registered goldfish_audio
goldfish_pdev_worker registered goldfish_fb
goldfish_pdev_worker registered smc91x
goldfish_pdev_worker registered goldfish_tty
goldfish_pdev_worker registered goldfish_tty
goldfish_pdev_worker registered goldfish_tty
goldfish_pdev_worker registered goldfish_rtc
goldfish_pdev_worker registered goldfish_timer
goldfish_pdev_worker registered goldfish_device_bus
goldfish_pdev_worker registered goldfish_interrupt_controller
ashmem: initialized
Installing knfsd (copyright (C) 1996 okir@monad.swb.de).
yaffs May 18 2009 21:56:58 Installing.
msgmni has been set to 183
alg: No test for stdrng (krng)
io scheduler noop registered
io scheduler anticipatory registered (default)
io scheduler deadline registered
io scheduler cfq registered
allocating frame buffer 320 * 480, got ffc10000
Console: switching to colour frame buffer device 40x30
console [ttyS0] enabled
brd: module loaded
loop: module loaded
nbd: registered device at major 43
smc91x.c: v1.1, sep 22 2004 by Nicolas Pitre <nico@cam.org>
eth0 (smc91x): not using net_device_ops yet
eth0: SMC91C11xFD (rev 1) at c684c000 IRQ 13 [nowait]
eth0: Ethernet addr: 52:54:00:12:34:56
goldfish nand dev0: size 4000000, page 2048, extra 64, erase 131072
goldfish nand dev1: size 4000000, page 2048, extra 64, erase 131072
goldfish nand dev2: size 4000000, page 2048, extra 64, erase 131072
mice: PS/2 mouse device common for all mice
*** events probe ***
events_probe() addr=0xc6854000 irq=17
events_probe() keymap=qwerty
input: qwerty as /devices/virtual/input/input0
goldfish_rtc goldfish_rtc: rtc core: registered goldfish_rtc as rtc0
logger: created 64K log 'log_main'
logger: created 256K log 'log_events'
logger: created 64K log 'log_radio'
IPv4 over IPv4 tunneling driver
GRE over IPv4 tunneling driver
TCP cubic registered
NET: Registered protocol family 17
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
802.1Q VLAN Support v1.8 Ben Greear <greearb@candelatech.com>
All bugs added by David S. Miller <davem@redhat.com>
VFP support v0.3: implementor 41 architecture 1 part 10 variant 9 rev 0
goldfish_rtc goldfish_rtc: setting system clock to 2009-05-19 05:21:03 UTC (1242710463)
Freeing init memory: 108K
init: cannot open '/initlogo.rle'
yaffs: passed flags ""
yaffs: Attempting MTD mount on 31.0, "mtdblock0"
yaffs_read_super: isCheckpointed 0
save exit: isCheckpointed 1
yaffs: dev is 32505857 name is "mtdblock1"
yaffs: passed flags ""
yaffs: Attempting MTD mount on 31.1, "mtdblock1"
yaffs: restored from checkpoint
yaffs_read_super: isCheckpointed 1
yaffs: dev is 32505858 name is "mtdblock2"
yaffs: passed flags ""
yaffs: Attempting MTD mount on 31.2, "mtdblock2"
yaffs_read_super: isCheckpointed 0
init: cannot find '/system/bin/playmp3', disabling 'bootsound'
# eth0: link up
warning: `rild' uses 32-bit capabilities (legacy support in use)


从这行打印开始,内核调用用户层的init,开始执行ramdisk中的程序.
init: cannot open '/initlogo.rle'
android的init 与标准linux 的init 逻辑有些差异.他包含开机显示, 像上面的打印则是开机logo的打印. 还包含监控服务的内容,以及udev的内容,以及.
init会读/init.rc这个配置文件,然后会读取/proc/cpuinfo中Hardware这一行的值,来选择读取/init.Hardware.rc这个文件.


ramdisk 目录层次:
.
|-- data
|-- default.prop
|-- dev
|-- init
|-- init.goldfish.rc
|-- init.rc
|-- proc
|-- sbin
|   `-- adbd
|-- sys
`-- system


目录中没有库文件,所以init与adbd都是静态链接程序.
init.rc 里会把主要的根文件系统(nand flash中一个分区)mount到/system 目录下,然后执行里面的一些后台程序.

yaffs2 image可以使用unyaffs解开(http://code.google.com/p/unyaffs):
.
|-- abc
|-- app
|   |-- AlarmClock.apk
|   |-- Browser.apk
|   |-- Calendar.apk
|   |-- CalendarProvider.apk
|   |-- Camera.apk
|   |-- Contacts.apk
|   |-- ContactsProvider.apk
|   |-- Development.apk
|   |-- DownloadProvider.apk
|   |-- DrmProvider.apk
|   |-- GoogleSearch.apk
|   |-- HTMLViewer.apk
|   |-- LatinIME.apk
|   |-- Launcher.apk
|   |-- MediaProvider.apk
|   |-- Mms.apk
|   |-- Music.apk
|   |-- PackageInstaller.apk
|   |-- Phone.apk
|   |-- Settings.apk
|   |-- SettingsProvider.apk
|   |-- SoundRecorder.apk
|   |-- SpareParts.apk
|   |-- SubscribedFeedsProvider.apk
|   |-- TelephonyProvider.apk
|   |-- Term.apk
|   `-- UserDictionaryProvider.apk
|-- bin
|   |-- am
|   |-- app_process
|   |-- applypatch
|   |-- bugreport -> dumpstate
|   |-- cat -> toolbox
|   |-- check_prereq
|   |-- chmod -> toolbox
|   |-- chown -> toolbox
|   |-- cmp -> toolbox
|   |-- dalvikvm
|   |-- date -> toolbox
|   |-- dbus-daemon
|   |-- dd -> toolbox
|   |-- debuggerd
|   |-- dexopt
|   |-- df -> toolbox
|   |-- dhcpcd
|   |-- dmesg -> toolbox
|   |-- dosfsck
|   |-- dumpcrash -> dumpstate
|   |-- dumpstate
|   |-- dumpsys
|   |-- dvz
|   |-- flash_image
|   |-- gdbserver
|   |-- getevent -> toolbox
|   |-- getprop -> toolbox
|   |-- gzip
|   |-- hd -> toolbox
|   |-- id -> toolbox
|   |-- ifconfig -> toolbox
|   |-- iftop -> toolbox
|   |-- ime
|   |-- input
|   |-- insmod -> toolbox
|   |-- installd
|   |-- ioctl -> toolbox
|   |-- iptables
|   |-- kill -> toolbox
|   |-- linker
|   |-- ln -> toolbox
|   |-- log -> toolbox
|   |-- logcat
|   |-- logwrapper
|   |-- ls -> toolbox
|   |-- lsmod -> toolbox
|   |-- mediaserver
|   |-- mkdir -> toolbox
|   |-- mkdosfs -> toolbox
|   |-- monkey
|   |-- mount -> toolbox
|   |-- mv -> toolbox
|   |-- netcfg
|   |-- netstat -> toolbox
|   |-- notify -> toolbox
|   |-- ping
|   |-- pm
|   |-- printenv -> toolbox
|   |-- ps -> toolbox
|   |-- pv2way_omx_engine_test
|   |-- pvplayer_engine_test
|   |-- qemud
|   |-- radiooptions
|   |-- reboot -> toolbox
|   |-- recovery
|   |-- renice -> toolbox
|   |-- rild
|   |-- rm -> toolbox
|   |-- rmdir -> toolbox
|   |-- rmmod -> toolbox
|   |-- route -> toolbox
|   |-- schedtest
|   |-- schedtop -> toolbox
|   |-- sdutil
|   |-- sendevent -> toolbox
|   |-- service
|   |-- servicemanager
|   |-- setconsole -> toolbox
|   |-- setprop -> toolbox
|   |-- sh
|   |-- showlease
|   |-- sleep -> toolbox
|   |-- smd -> toolbox
|   |-- start -> toolbox
|   |-- stop -> toolbox
|   |-- surfaceflinger
|   |-- svc
|   |-- sync -> toolbox
|   |-- system_server
|   |-- test_pvauthorengine
|   |-- toolbox
|   |-- top -> toolbox
|   |-- umount -> toolbox
|   |-- vmstat -> toolbox
|   |-- vold
|   |-- watchprops -> toolbox
|   `-- wipe -> toolbox
|-- build.prop
|-- etc
|   |-- NOTICE.html.gz
|   |-- apns-conf.xml
|   |-- bookmarks.xml
|   |-- dbus.conf
|   |-- dhcpcd
|   |   |-- dhcpcd-hooks
|   |   |   |-- 01-test
|   |   |   |-- 20-dns.conf
|   |   |   `-- 95-configured
|   |   |-- dhcpcd-run-hooks
|   |   `-- dhcpcd.conf
|   |-- event-log-tags
|   |-- hosts
|   |-- init.goldfish.sh
|   |-- permissions
|   |   `-- platform.xml
|   |-- pvplayer.cfg
|   |-- security
|   |   |-- cacerts.bks
|   |   `-- otacerts.zip
|   `-- vold.conf
|-- fonts
|   |-- DroidSans-Bold.ttf
|   |-- DroidSans.ttf
|   |-- DroidSansFallback.ttf
|   |-- DroidSansMono.ttf
|   |-- DroidSerif-Bold.ttf
|   |-- DroidSerif-BoldItalic.ttf
|   |-- DroidSerif-Italic.ttf
|   `-- DroidSerif-Regular.ttf
|-- framework
|   |-- am.jar
|   |-- android.awt.jar
|   |-- android.policy.jar
|   |-- android.test.runner.jar
|   |-- com.android.im.plugin.jar
|   |-- core.jar
|   |-- ext.jar
|   |-- framework-res.apk
|   |-- framework-tests.jar
|   |-- framework.jar
|   |-- ime.jar
|   |-- input.jar
|   |-- monkey.jar
|   |-- pm.jar
|   |-- services.jar
|   `-- svc.jar
|-- lib
|   |-- browsertestplugin.so
|   |-- hw
|   |   `-- sensors.goldfish.so
|   |-- libEGL.so
|   |-- libFFTEm.so
|   |-- libGLESv1_CM.so
|   |-- libaes.so
|   |-- libagl.so
|   |-- libandroid_runtime.so
|   |-- libandroid_servers.so
|   |-- libaudioflinger.so
|   |-- libc.so
|   |-- libc_debug.so
|   |-- libcameraservice.so
|   |-- libcorecg.so
|   |-- libcrypto.so
|   |-- libctest.so
|   |-- libcutils.so
|   |-- libdbus.so
|   |-- libdl.so
|   |-- libdrm1.so
|   |-- libdrm1_jni.so
|   |-- libdvm.so
|   |-- libemoji.so
|   |-- libexif.so
|   |-- libexpat.so
|   |-- libhardware.so
|   |-- libhardware_legacy.so
|   |-- libicudata.so
|   |-- libicui18n.so
|   |-- libicuuc.so
|   |-- libjni_latinime.so
|   |-- liblog.so
|   |-- libm.so
|   |-- libmedia.so
|   |-- libmedia_jni.so
|   |-- libmediaplayerservice.so
|   |-- libnativehelper.so
|   |-- libnetutils.so
|   |-- libomx_aacdec_sharedlibrary.so
|   |-- libomx_amrdec_sharedlibrary.so
|   |-- libomx_amrenc_sharedlibrary.so
|   |-- libomx_avcdec_sharedlibrary.so
|   |-- libomx_avcenc_sharedlibrary.so
|   |-- libomx_m4vdec_sharedlibrary.so
|   |-- libomx_m4venc_sharedlibrary.so
|   |-- libomx_mp3dec_sharedlibrary.so
|   |-- libomx_sharedlibrary.so
|   |-- libopencore_2way.so
|   |-- libopencore_author.so
|   |-- libopencore_common.so
|   |-- libopencore_download.so
|   |-- libopencore_downloadreg.so
|   |-- libopencore_mp4local.so
|   |-- libopencore_mp4localreg.so
|   |-- libopencore_net_support.so
|   |-- libopencore_player.so
|   |-- libopencore_rtsp.so
|   |-- libopencore_rtspreg.so
|   |-- libpagemap.so
|   |-- libpixelflinger.so
|   |-- libreference-ril.so
|   |-- libril.so
|   |-- libsgl.so
|   |-- libskiagl.so
|   |-- libsonivox.so
|   |-- libsoundpool.so
|   |-- libsqlite.so
|   |-- libsrec_jni.so
|   |-- libssl.so
|   |-- libstdc++.so
|   |-- libsurfaceflinger.so
|   |-- libsystem_server.so
|   |-- libthread_db.so
|   |-- libui.so
|   |-- libutils.so
|   |-- libvorbisidec.so
|   |-- libwbxml.so
|   |-- libwbxml_jni.so
|   |-- libwebcore.so
|   |-- libwpa_client.so
|   |-- libxml2wbxml.so
|   `-- libz.so
|-- usr
|   |-- keychars
|   |   |-- qwerty.kcm.bin
|   |   |-- qwerty2.kcm.bin
|   |   `-- tuttle2.kcm.bin
|   |-- keylayout
|   |   |-- AVRCP.kl
|   |   |-- qwerty.kl
|   |   `-- tuttle2.kl
|   |-- share
|   |   |-- bmd
|   |   |   |-- RFFspeed_501.bmd
|   |   |   `-- RFFstd_501.bmd
|   |   `-- zoneinfo
|   |       |-- zoneinfo.dat
|   |       |-- zoneinfo.idx
|   |       `-- zoneinfo.version
|   `-- srec
|       `-- config
|           `-- en.us
|               |-- baseline.par
|               |-- baseline11k.par
|               |-- baseline8k.par
|               |-- dictionary
|               |   |-- basic.ok
|               |   |-- cmu6plus.ok.zip
|               |   `-- enroll.ok
|               |-- g2p
|               |   `-- en-US-ttp.data
|               |-- grammars
|               |   `-- VoiceDialer.g2g
|               `-- models
|                   |-- generic.swiarb
|                   |-- generic11.lda
|                   |-- generic11_f.swimdl
|                   |-- generic11_m.swimdl
|                   |-- generic8.lda
|                   |-- generic8_f.swimdl
|                   `-- generic8_m.swimdl
`-- xbin
    |-- add-property-tag
    |-- backup
    |-- check-lost+found
    |-- cpueater
    |-- crasher
    |-- daemonize
    |-- dbus-monitor
    |-- dbus-send
    |-- dexdump
    |-- latencytop
    |-- librank
    |-- nc
    |-- netperf
    |-- netserver
    |-- opcontrol
    |-- oprofiled
    |-- pppd
    |-- procmem
    |-- procrank
    |-- scp
    |-- showmap
    |-- showslab
    |-- sqlite3
    |-- ssh
    |-- strace
    |-- su
    `-- timeinfo

25 directories, 302 files




link状态上报

在phy的内核线程里,会周期性的通过MII查询link状态.
        if (phydev->link) {
                phydev->state = PHY_RUNNING;
                netif_carrier_on(phydev->attached_dev);
            } else {
                phydev->state = PHY_NOLINK;
                netif_carrier_off(phydev->attached_dev);
            }

然后通过下面两个函数来进行处理:,
void netif_carrier_on(struct net_device *dev)
{
    if (test_and_clear_bit(__LINK_STATE_NOCARRIER, &dev->state))
        linkwatch_fire_event(dev);
    if (netif_running(dev))
        __netdev_watchdog_up(dev);
}

void netif_carrier_off(struct net_device *dev)
{
    if (!test_and_set_bit(__LINK_STATE_NOCARRIER, &dev->state))
        linkwatch_fire_event(dev);
}
会把状态设到dev->state里.  并调用linkwatch_fire_event来在list:lweventlist中添加一个节点.并由workqueue:linkwatch_work来处理.主要的处理流程为:进行一些协议栈方面的维护工作, 然后调用 netdev_state_change 来notify netdev_chain(事件为NETDEV_CHANGE),以及rtmsg_ifinfo来向group:RTNLGRP_LINK广播RTM_NEWLINK信息.   注册 netdev_chain的包括 rtnetlink. 但其在回调里没作处理. 用户程序通过netlink接收RTNLGRP_LINK的消息即可及时得到通知.

gnome的NetworkManager以及ifplugd间接或直接的使用这种机制.

netlink interface

其主要是用来配置网络的标准化接口. 文章Understanding And Programming With Netlink Sockets(http://people.redhat.com/nhorman/papers/netlink.pdf)作了基本介绍.

使用示例见: http://www.wlug.org.nz/LinuxNetlinkSocketExample.
我将其代码略微修改,以得到内核层link状态报告,

#include <sys/socket.h>
#include <unistd.h>
#include <err.h>
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>

#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <linux/if.h>

#if 0
//#define MYPROTO NETLINK_ARPD
#define MYMGRP RTMGRP_NEIGH
// if you want the above you'll find that the kernel must be compiled with CONFIG_ARPD, and
// that you need MYPROTO=NETLINK_ROUTE, since the kernel arp code {re,ab}uses rtnl (NETLINK_ROUTE)

#else
#if 0
#define MYPROTO NETLINK_ROUTE
#define MYMGRP RTMGRP_IPV4_ROUTE
#else
#define MYPROTO NETLINK_ROUTE
#define MYMGRP RTNLGRP_LINK
#endif
#endif

struct msgnames_t {
        int id;
        char *msg;
} typenames[] = {
#define MSG(x) { x, #x }
        MSG(RTM_NEWROUTE),
        MSG(RTM_DELROUTE),
        MSG(RTM_GETROUTE),
#undef MSG
        {0,0}
};

   

char *lookup_name(struct msgnames_t *db,int id)
{
        static char name[512];
        struct msgnames_t *msgnamesiter;
        for(msgnamesiter=db;msgnamesiter->msg;++msgnamesiter) {
                if (msgnamesiter->id == id)
                        break;
        }
        if (msgnamesiter->msg) {
                return msgnamesiter->msg;
        }
        snprintf(name,sizeof(name),"#%i",id);
        return name;
}

int open_netlink()
{
        int sock = socket(AF_NETLINK,SOCK_RAW,MYPROTO);
        struct sockaddr_nl addr;

        memset((void *)&addr, 0, sizeof(addr));

        if (sock<0)
                return sock;
        addr.nl_family = AF_NETLINK;
        addr.nl_pid = getpid();
        addr.nl_groups = MYMGRP;
        if (bind(sock,(struct sockaddr *)&addr,sizeof(addr))<0)
                return -1;
        return sock;
}

int read_event(int sock)
{
        struct sockaddr_nl nladdr;
        struct msghdr msg;
        struct iovec iov[2];
        struct nlmsghdr nlh;
        char buffer[65536];
        int ret;
        iov[0].iov_base = (void *)&nlh;
        iov[0].iov_len = sizeof(nlh)+sizeof(struct ifinfomsg);
        iov[1].iov_base = (void *)buffer;
        iov[1].iov_len = sizeof(buffer);
        msg.msg_name = (void *)&(nladdr);
        msg.msg_namelen = sizeof(nladdr);
        msg.msg_iov = iov;
        msg.msg_iovlen = sizeof(iov)/sizeof(iov[0]);
        ret=recvmsg(sock, &msg, 0);
        if (ret<0) {
                return ret;
        }
        printf("Type: %i (%s)\n",(nlh.nlmsg_type),lookup_name(typenames,nlh.nlmsg_type));
        printf("Flag:");
#define FLAG(x) if (nlh.nlmsg_flags & x) printf(" %s",#x)
        FLAG(NLM_F_REQUEST);
        FLAG(NLM_F_MULTI);
        FLAG(NLM_F_ACK);
        FLAG(NLM_F_ECHO);
        FLAG(NLM_F_REPLACE);
        FLAG(NLM_F_EXCL);
        FLAG(NLM_F_CREATE);
        FLAG(NLM_F_APPEND);
#undef FLAG
        printf("\n");
        printf("Seq : %i\n",nlh.nlmsg_seq);
        printf("Pid : %i\n",nlh.nlmsg_pid);
        printf("\n");

        {
            struct ifinfomsg *ifi;
            ifi= NLMSG_DATA((unsigned char *) &nlh);
            if(ifi->ifi_flags & IFF_LOWER_UP)
                printf("link up:[%x]\n",ifi->ifi_flags);
            else
                printf("link down:[%x]\n",ifi->ifi_flags);
        }
        return 0;
}

int main(int argc, char *argv[])
{
        int nls = open_netlink();
        if (nls<0) {
                err(1,"netlink");
        }

        while (1)
                read_event(nls);
        return 0;
}

Saturday, May 23, 2009

d-bus

d-bus  资料在这里有很多.
使用示例可用文档: Using the D-Bus C API(http://dbus.freedesktop.org/doc/dbus/libdbus-tutorial.html)所附的dbus-example.c.
编译如下:
gcc dbus-example.c -o dbus-example `pkg-config --cflags --libs dbus-1`

pkg-config

pkg-config 可用来取得使用某个库来进行开发时所需的编译参数. 如:
[dybbuk@localhost tmp]$ pkg-config --cflags --libs dbus-1
-I/usr/include/dbus-1.0 -I/usr/lib/dbus-1.0/include  -L/lib -ldbus-1 

库的名字必須跟/usr/lib/pkgconfig 相应的.pc文件的名字一样.  否则就无法取得.

Thursday, May 21, 2009

linux large file support

LFS support

在老的文件操作接口以及实现中,使用整形数来保存偏移或字节数,故在32bit机器上存在最大只能表示2G的问题.
像ftell,feek:
 int fseek(FILE *stream, long offset, int whence);
 long ftell(FILE *stream);

要支持2G以上大文件,有几个点要注意:物理文件系统,文件系统接口(包括kernel,libc),以及文件操作接口选择和编译.

==文件系统对大文件的支持情况==
FAT最大单个文件2G,FAT32最大4G,NTFS最大128G

nfs: version 2只能支持2G的文件,version 3支持LFS.如使用 nfs v2,则在fseeo超过2G的文件位置时会报错,非法参数.
一般nfs server支持version 2,version3, version 4版本的nfs传输.如要强制使用nfs version 3,可以在mount时加上参数, nfsvers=3.否则默认一般都是version2传输.内核mount nfs根文件系统时的参数同样可以加上这个参数:nfsroot=server-ip:root-dir,nfsvers=3.

ext2/3:支持大文件.

==kernel==
文件系统驱动是按照文件系统标准在实现,在系统调用这一层,也都默认能支持大文件.

==c库==
为此glibc/uclibc加入了LFS(large file support)的特性.一般的版本这个特性都是打开了的. 故要支持LFS,一般不用重新编译.

==c接口的使用和编译==
像ftell, fseek这两个接口,在标准c中的原型定义为:
       int fseek(FILE *stream, long offset, int whence);
       long ftell(FILE *stream);
故在32bit操作系统下,这两个接口是无法支持大文件的.必須使用其它接口.

其它文件接口,不存在上面的情况,要么是没有使用到跟offset,size相关的参数,像fopen等,要么其涉及到offset和size的参数用的是非标准数据类型(如off_t等),标准里对这种非标准数据类型没有定义.

故在实际glibc/uclibc中, 在实现涉及到offset和size等的非标准数据类型时,提供了两套.一套为32位的.一套为64位的. 使用宏来控制_LARGEFILE_SOURCE _LARGEFILE64_SOURCE _FILE_OFFSET_BITS 来控制.

故要在程序中支持大文件,只需要加上 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 的编译选项即可.

在有些文档中,会介绍64位的文件系统接口,如:
 fopen->fopen64
 stat->stat64
 fstat->fstat64
 lstat->lstat64
 fseeko->fseeko64
 ftello->ftello64

但不推荐直接这些函数,因为这属于glibc/uclibc内部函数, 不是标准函数.代码移植性比较差. 并且使用-D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64宏达到的是类似效果.由编译器用宏展开或符号重名的方式来调用相应的64位的文件接口.

==其它==
1.如不打开上述编译控制宏, fopen默认情况下打开大文件会失败,报错: Value too large for defined data type

2. busybox有CONFIG_LFS选项来决定是否使用上述三个宏.


[[Category:文件系统]][[Category:linux]]

Sunday, May 17, 2009

android emulator初探

android emulator基于qemu开发. 源码位于external/qemu目录下.
但从使用上看,看不出qemu的影子.但实现上emulator与qemu没有太大区别.

以命令行解析为例
使用 ./emulator -debug all 启动,可以看到类似下面的打印:
emulator: argv[00] = "./emulator"
emulator: argv[01] = "-kernel"
emulator: argv[02] = "/home/dybbuk/work/android_dev/mydroid/prebuilt/android-arm/kernel/kernel-qemu"
emulator: argv[03] = "-initrd"
emulator: argv[04] = "/home/dybbuk/work/android_dev/mydroid/out/target/product/generic//ramdisk.img"
emulator: argv[05] = "-nand"
emulator: argv[06] = "system,size=0x4200000,initfile=/home/dybbuk/work/android_dev/mydroid/out/target/product/generic//system.img"
emulator: argv[07] = "-nand"
emulator: argv[08] = "userdata,size=0x4200000,file=/tmp/android/emulator-YrPtDf"
emulator: argv[09] = "-nand"
emulator: argv[10] = "cache,size=0x4200000"
emulator: argv[11] = "-serial"
emulator: argv[12] = "android-kmsg"
emulator: argv[13] = "-serial"
emulator: argv[14] = "stdio"
emulator: argv[15] = "-serial"
emulator: argv[16] = "android-qemud"
emulator: argv[17] = "-append"
emulator: argv[18] = "qemu=1 console=ttyS0 androidboot.console=ttyS1 android.checkjni=1 android.qemud=ttyS2 android.ndns=3"
emulator: argv[19] = "-m"
emulator: argv[20] = "96"
emulator: argv[21] = "-clock"
emulator: argv[22] = "unix"
这些参数就是emulator调用qemu时所用的参数. 你如果用过qemu的话,会对部分参数有些印象.
所以从命令行参数来看,emulator 只不过是对qemu 作了封装, 使得易于使用.

以qemu的文档来分析各个参数的作用:
‘-kernel bzImage’
    Use bzImage as kernel image.
‘-append cmdline’
    Use cmdline as kernel command line
‘-initrd file’
    Use file as initial ram disk.
‘-clock method’
    Force the use of the given methods for timer alarm. To see what timers are available use -clock ?.
‘-m megs’
    Set virtual RAM size to megs megabytes. Default is 128 MiB. Optionally, a suffix of “M” or “G” can be used to signify a value in megabytes or gigabytes respectively.
‘-serial dev’
    Redirect the virtual serial port to host character device dev. The default device is vc in graphical mode and stdio in non graphical mode.
    This option can be used several times to simulate up to 4 serial ports.
‘-nand’
    这个应该是android版的qemu新增的参数.

emulator使用tip:
1.  以终端作为虚拟机的串口以及串口控制台.
添加: -show-kernel -shell 选项.

2. 使用其它的kernel image 文件:
 /home/dybbuk/work/android_dev/mydroid/out/host/linux-x86/bin/emulator -sysdir /home/dybbuk/work/android_dev/mydroid/out/target/product/generic/ -system /home/dybbuk/work/android_dev/mydroid/out/target/product/generic/system.img -ramdisk /home/dybbuk/work/android_dev/mydroid/out/target/product/generic//ramdisk.img -kernel /home/dybbuk/work/android_dev/mydroid/kernel/arch/arm/boot/zImage

Monday, May 11, 2009

同事的小孩

上一张帅哥的靓照, 来招揽人气.

周日去看了一下同事的小孩..挺可爱的一个小孩.



Sunday, May 10, 2009

fedora 9 编译 Android

android
    主站:http://www.android.com/
    application develop based on the platform: http://developer.android.com/
    platform develop:http://source.android.com/  


源代码的下载说明页面是:http://source.android.com/download
最新的release:Release features


(1) 配置repo账户
git config --global user.email "xxxxx@xxxxxxx"
git config --global user.name "xxxxxx"

(2)开始准备下载android
cd ~/work/android_dev
mkdir mydroid
cd mydroid
../bin/repo init -u git://android.git.kernel.org/platform/manifest.git -b android-1.5

(3)开始下载android platform的源代码
repo sync
这个操作会持续一段时间,看网速了,只有800M左右。

(4)编译
make
我这边编译时间在一小时以上
编译完毕以后,会发现在代码目录下多了一个目录:
~/work/android_dev/mydroid/out

如果报错:
which: no javac in (/usr/lib/qt-3.3/bin:/usr/kerberos/bin:/usr/lib/ccache:/usr/local/bin:/usr/bin:/bin:/opt/real/RealPlayer:/home/dybbuk/bin:/sbin/:/usr/sbin/:/opt/real/RealPlayer)
 则说明你没有安装 jdk 5.0..  去 http://java.sun.com/javase/downloads/5/jdk  下载 jdk  安装后,  设置环境变量:
export ANDROID_JAVA_HOME=/usr/java/jdk1.5.0_18
export PATH=/usr/java/jdk1.5.0_18/bin:$PATH

(5)开始验证生成的结果
export ANDROID_PRODUCT_OUT=~/work/android_dev/mydroid/out/target/product/generic
~/work/android_dev/mydroid/out/host/linux-x86/bin/emulator
应该看到开机的画面(第一次开启的时候,应该还有一个向google反馈的一个对话框,按下确定即可)。


paltform source layout:
Project
    Description
bionic
    C runtime: libc, libm, libdl, dynamic linker
bootloader/legacy
    Bootloader reference code
build
    Build system
dalvik
    Dalvik virtual machine
development
    High-level development and debugging tools
frameworks/base
    Core Android app framework libraries
frameworks/policies/base
    Framework configuration policies
hardware/libhardware
    Hardware abstraction library
hardware/ril
    Radio interface layer
kernel
    Linux kernel
prebuilt     Binaries to support Linux and Mac OS builds
recovery
    System recovery environment
system/bluetooth
    Bluetooth tools
system/core     Minimal bootable environment
system/extras
    Low-level debugging/inspection tools
system/wlan/ti     TI 1251 WLAN driver and tools

===============================================
kernel
===============================================
下载的kernel为manifest 的kernel
用于模拟器的板型为goldfish,所以要编译kernel需要把kernel切换到 goldfish 的分支.
[dybbuk@localhost kernel]$ git branch -r
  korg/android-2.6.25
  korg/android-2.6.27
  korg/android-2.6.29
  korg/android-goldfish-2.6.27
  korg/android-goldfish-2.6.29
  m/android-1.5
  m/master
[dybbuk@localhost kernel]$ git checkout korg/android-goldfish-2.6.29
toolchain:
直接用android里自带的:
 export PATH=/home/dybbuk/work/android_dev/mydroid/prebuilt/linux-x86/toolchain/arm-eabi-4.3.1/bin:$PATH
make ARCH=arm CROSS_COMPILE=arm-eabi- goldfish_defconfig
make ARCH=arm CROSS_COMPILE=arm-eabi-
即可生成emulator所用的zImage