網頁

2009年10月26日 星期一

CGI debug

Web server will redirect STDIN, STDOUT and STDERR to CGI interface so the following function is used to print out debug messages from C code.

Function 1:
void debug_printf(const char *degmsg, ... )  
 {  
     int old = dup(STDOUT);  
     int ttyfd ;  
     int ret;  
     va_list ap;  
     char msg[512];  
     
     ttyfd = open("/dev/ttyS0", O_RDWR);  
     va_start(ap,degmsg);  
     ret = vsprintf(msg,degmsg,ap);  
     va_end(ap);  
     dup2(ttyfd, STDOUT);  
     close(ttyfd);  
     printf("%s",msg);  
     dup2(old, STDOUT);   }

Function 2:

void debug_printf(const char *degmsg, ... ){  
     va_list ap;  
     int ret;  
     FILE *con_ptr;  
     char msg[512];  
     
     va_start(ap,degmsg);  
     ret = vsprintf(msg,degmsg,ap);  
     va_end(ap);  
     con_ptr = fopen("/dev/ttyS1","w+");;      
     if (!con_ptr) {  
         perror("fopen");  
     }  
     fprintf(con_ptr,"%s",msg);  
     fflush(con_ptr);  
     fclose(con_ptr);  
 }

2009年10月1日 星期四

How to mount JFFS2 image

Use memory to emulate the MTD device
mknod /tmp/mtdblock0 b 31 0
modprobe mtdblock
modprobe mtdram total_size=65536 erase_size=256

modprobe jffs2

dd if=image.jffs2 of=/tmp/mtdblock0

mkdir /mnt/jffs2
mount -t jffs2 /tmp/mtdblock0 /mnt/jffs2

2009年7月3日 星期五

IPV6 DHCPV6 Configuration

Router Advertisement Daemon (radvd)
/etc/radvd.conf

interface eth0 { 
  AdvSendAdvert on; 
  MinRtrAdvInterval 3; 
  MaxRtrAdvInterval 10; 
  prefix 2001:0db8:0100:f101::/64 { 
     AdvOnLink on; 
    #Disable Stateless Address Autoconfiguration 
    #AdvAutonomous on; 
    AdvRouterAddr on; 
  }; 
};
 
Wide-DHCPv6
Server configuration: dhcp6s.conf

option domain-name-servers 2001:470:1f01:2191::1 2001:470:1f01:2191::2; 
option domain-name "dean.net"; 
interface eth0{ 
  address-pool pool1 3600; 
}; 
pool pool1 { 
  range 2001:5c0:1101:b700::1000 to 2001:5c0:1101:b700::2000 ; 
}; 
host host0 { 
  duid 00:00:00:00:a0:a0; 
  prefix 3ffe:ffff:102::120/64 infinity; 
};
Client configuration
DHCPV6 client for the stateful autoconfigutation

interface eth0 {
         send ia-na 0;
         request domain-name-servers;
         request domain-name;
         script "/tmp/dean/dhcp6c-script";
};
id-assoc na 0 {
         # non-temporary addresses
};
DHCPV6 client for the stateless autoconfigutation
interface eth0
{
 information-only;


 request domain-name-servers;
 request domain-name;
 script "/tmp/dean/dhcp6c-script";

};
DHCPV6 script
update DNS in resolv.conf
#!/bin/sh

if [ -n "$new_domain_name" -o -n "$new_domain_name_servers" ]; then
    new_resolv_conf=/tmp/resolv.conf.dhcp6c-new
    rm -f $new_resolv_conf
    if [ -n "$new_domain_name" ]; then
        echo search $new_domain_name >> $new_resolv_conf
    fi
    if [ -n "$new_domain_name_servers" ]; then
        for nameserver in $new_domain_name_servers; do
            echo nameserver $nameserver >> $new_resolv_conf
        done
    fi

    # To preserve IPv4 informations...
    cat /etc/resolv.conf >> $new_resolv_conf
    mv -f $new_resolv_conf /etc/resolv.conf
fi

exit 0







2009年6月25日 星期四

Shell script tricks

1. The array of shell script 
names=( Jennifer Tonya Anna Sadie )
for name in ${names[@]}
do
   echo $name
done
names=( Jennifer Tonya Anna Sadie )
for (( i = 0 ; i < ${#names[@]} ; i++ ))
do
    echo ${names[$i]}
done
2. Variable substitution for shell script 
$DEVICE0=eth0
$echo "Configure interface " ${!DEVICE${i}}
$n=1
$ eval echo \${$n}
$ n="date"
$ echo $($n)
Output :Wed May 21 20:39:00 EEST 2008
3. Increment i in the while loop 
i=$(($i+1))
i=`expr i + $i`

2009年6月15日 星期一

Re-entrant vs Thread safe

Both concepts of reentrancy and thread safety relate to the way functions handle resources. However, they are not the same. While the concept of reentrancy can affect the external interface of a function, thread safety only concerns the implementation of the function and not its external interface.
  • In most cases, to make a non-reentrant function reentrant, its external interface must be modified such that all data is provided by the caller of the function.
  • To make a thread-unsafe function thread-safe, only the implementation needs to be changed, usually by addingsynchronization blocks to protect shared resources from concurrent accesses by different threads.
Therefore, reentrancy is a more fundamental property than thread-safety and by definition, leads to thread-safety: Every reentrant function is thread-safe; however, not every thread-safe function is reentrant.
Reference from http://en.wikipedia.org/wiki/Reentrant_(subroutine)

2009年6月9日 星期二

How to show the page table entry


excerpt from arch/arm/mm/fault.c
void show_pte(struct mm_struct *mm, unsigned long addr)
{
pgd_t *pgd;

if (!mm)
mm = &init_mm;

printk(KERN_ALERT "pgd = %p\n", mm->pgd);
pgd = pgd_offset(mm, addr);
printk(KERN_ALERT "[%08lx] *pgd=%08lx", addr, pgd_val(*pgd));

do {
pmd_t *pmd;
pte_t *pte;

if (pgd_none(*pgd))
break;

if (pgd_bad(*pgd)) {
printk("(bad)");
break;
}

pmd = pmd_offset(pgd, addr);
#if PTRS_PER_PMD != 1
printk(", *pmd=%08lx", pmd_val(*pmd));
#endif

if (pmd_none(*pmd))
break;

if (pmd_bad(*pmd)) {
printk("(bad)");
break;
}

#ifndef CONFIG_HIGHMEM
/* We must not map this if we have highmem enabled */
pte = pte_offset_map(pmd, addr);
printk(", *pte=%08lx", pte_val(*pte));
printk(", *ppte=%08lx", pte_val(pte[-PTRS_PER_PTE]));
pte_unmap(pte);
#endif
} while(0);

printk("\n");
}

crontab

Crontab command
#export to the file
crontab -l > filename
# import from the file
crontab filename 
# import from the file for the specific user
crontab -u user filename 
# edit
crontab -e 
# delete all
crontab -r 

Crontab special usage 


EntryDescriptionEquivalent To
@rebootRun once, at startup.None
@yearlyRun once a year0 0 1 1 *
@annually(same as @yearly)0 0 1 1 *
@monthlyRun once a month0 0 1 * *
@weeklyRun once a week0 0 * * 0
@dailyRun once a day0 0 * * *
@midnight(same as @daily)0 0 * * *
@hourlyRun once an hour0 * * * *


Crontab Example

# .---------------- minute (0 - 59) 
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# | | | | |
# * * * * * command to be executed

minhourday/monthmonthday/week Execution time
30011,6,12*-- 00:30 Hrs  on 1st of Jan, June & Dec.

:

020*101-5--8.00 PM every weekday (Mon-Fri) only in Oct.

:

001,10,15**-- midnight on 1st ,10th & 15th of month

:

5,10010*1-- At 12.05,12.10 every Monday & on 10th of every month
:

 
*/8 * * * * root init 6  After 8 minutes , execute "reboot" command
ps: "*/8" in the minute time field is equivalent to "0,8,16,24,32,48,56"

2009年6月8日 星期一

Linux 2.6 Driver Template


#include <linux/module.h>
#include <linux/config.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <asm/io.h>

#include <linux/fs.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>

typedef struct
{
void **data;
struct cdev *cdev ;

}DBG_Dev_Tag;

#define DBG_MAJOR 111
#define DBG_MINOR 1
#define MAXDEVICENUM 1

#define DEBUG_IOC_MAGIC 'D'
#define DEBUG_IOCSHOWDEB _IOR(DEBUG_IOC_MAGIC, 1, int)

DBG_Dev_Tag *DBG_devices;


int dbg_major = DBG_MAJOR;
int dbg_minor;

static struct file_operations DBG_fops =
{
.ioctl = DBG_ioctl,
.read = DBG_read,
.write = DBG_write,
.open = DBG_open,
.release = DBG_release,
};

int DBG_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
struct net_device *dev = &_wpcm450_netdevice;

switch (cmd)
{
case DEBUG_IOCSHOWDEB:
//show something

break;
default:
break;
}

return 0;
}

ssize_t DBG_read (struct file *filp, char *buf, size_t count, loff_t *offset)
{
return 0;
}

ssize_t DBG_write (struct file *file, const char *buf, size_t count, loff_t *offset)
{
return 0;
}

static int DBG_open(struct inode *inode, struct file *filp)
{
DBG_Dev_Tag *dev;

dev = container_of (inode->i_cdev,DBG_Dev_Tag,cdev);

filp-> private_data = dev;

return 0;
}

static int DBG_release(struct inode *inode, struct file *filp)
{


return 0;
}



static void dbg_setup_cdev(DBG_Dev_Tag *dev,int index)
{
int err;
int dev_id = MKDEV(dbg_major,dbg_minor + index );

cdev_init(dev->cdev,&DBG_fops);

dev->cdev->owner = THIS_MODULE;

dev->cdev->ops = &DBG_fops;

err = cdev_add(dev->cdev,dev_id,1);

if (err)
printk ("error %x adding dbg%x\n",err,index);

}


static int __init DBG_init(void)
{
int result;
dev_t dev_id;


DBG_devices = kmalloc (sizeof (DBG_Dev_Tag) * MAXDEVICENUM ,GFP_KERNEL);

if (DBG_devices == NULL)
{
result = -ENOMEM;
return result;
}

memset(DBG_devices, 0, MAXDEVICENUM * sizeof(DBG_Dev_Tag));

if (dbg_major)
{
dev_id = MKDEV(dbg_major,dbg_minor);

result = register_chrdev_region(dev_id, 1, "debug");
}
else
{
result = alloc_chrdev_region(&dev_id,DBG_MINOR,1,"dbg");
dbg_major = MAJOR(dev_id);
}

if (result < 0 )
{
printk ("can't get major %d\n",dbg_major);
return result;
}

DBG_devices->cdev = cdev_alloc();

dbg_setup_cdev(DBG_devices,1);

return 0;
}

static void __exit DBG_exit(void)
{
dev_t dev_id;

kfree(DBG_devices);

cdev_del(DBG_devices ->cdev);

dev_id = MKDEV(dbg_major,dbg_minor);
unregister_chrdev_region(dev_id,1);
return;
}

MODULE_AUTHOR("XXXXXXXXXX");
MODULE_DESCRIPTION("Debug driver");
MODULE_LICENSE("GPL");

module_init(DBG_init);
module_exit(DBG_exit);

//**************************Makefile *******************************
KERNELDIR =   obj-m := test_drv.o
#combine two drivers into the one. 
#test_drv-objs := testA_drv.o testB_drv.o  
ifneq ($(KERNELRELEASE),)  
CFLAGS +=  -D__KERNEL__ -DMODULE  -Wall -DEXPORT_SYMTAB -O2  
else  
all:  
 $(MAKE) -C $(KERNELDIR) M=$(shell pwd) modules endif 

2009年6月5日 星期五

TCP keepalive under linux

TCP keepalive During TCP connection idle
Main goal:
  • Checking for dead peers
  • Preventing disconnection due to network inactivity- TCP connections through NATs or proxy but they keep limited memory resources (mantain a few TCP connections, discard old connections)
How to use TCP keepalive under Linux
  • tcp_keepalive_time - the interval between the last data packet sent (simple ACKs are not considered data) and the first keepalive probe; after the connection is marked to need keepalive
  • tcp_keepalive_intvl - the interval between subsequential keepalive probes, regardless of what the connection has exchanged in the meantime
  • tcp_keepalive_probes - the number of unacknowledged probes to send before considering the connection dead and notifying the application layer
procfs interface

echo 20 > /proc/sys/net/ipv4/tcp_keepalive_probes

echo 600 > /proc/sys/net/ipv4/tcp_keepalive_time

echo 60 > /proc/sys/net/ipv4/tcp_keepalive_intvl
sysctl interface


sysctl -w \

> net.ipv4.tcp_keepalive_time=600 \

> net.ipv4.tcp_keepalive_intvl=60 \

> net.ipv4.tcp_keepalive_probes=20

How to program network applications with TCP keepalive
  • System call :setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen)
  • Other three socket options for the current socket overide system-wide variables as the follwoing
TCP_KEEPCNT: overrides tcp_keepalive_probes
TCP_KEEPIDLE: overrides tcp_keepalive_time
TCP_KEEPINTVL: overrides tcp_keepalive_intvl
reference from http://tldp.org/HOWTO/html_single/TCP-Keepalive-HOWTO/#whatis