2022年5月19日 星期四
[Raspberry] 如何製作Raspberry Pi 4的Android Image
2022年5月18日 星期三
[Raspberry] Raspberry Pi OS Image Download
https://ubuntu-mate.org/download/armhf/
https://ubuntu-mate.org/download/arm64/
https://konstakang.com/devices/rpi3/
https://sourceforge.net/projects/win32diskimager/
[Android] Build busybox
1. 下載busybox source code
https://busybox.net/downloads/
2. 解壓縮
# tar jxvf busybox-1.35.0.tar.bz2
3. 設定成靜態編譯
# make menuconfig
然後選Settings ---> [*] Build static binary (no shared libs)
Exit後存檔
(補充: 在Android下編譯指令程式不是透過Android.mk時,都需靜態編譯)
4. 編譯
# make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
(請先確認cross compiler是甚麼版本,上面是arm的)
例如arm64是aarch64-linux-gnu-
例如mips是aarch64-linux-gnu-
5. 編譯完後可以看到busybox,你可以下file指令來確認
# file busybox
busybox: ELF 32-bit LSB executable, ARM, EABI5 version 1 (GNU/Linux), statically linked, for GNU/Linux 3.2.0, BuildID[sha1]=413e4eba5bb276bb28feae5785c10862f9c8d867, stripped
2022年5月17日 星期二
[Android] SELinux avc dennied
audit(0.0:67): avc: denied { write } for path="/dev/block/vold/93:96" dev="tmpfs" ino=/1263 scontext=u:r:kernel:s0 tcontext=u:object_r:block_device:s0 tclass=blk_file permissive=0
[Android] SELinux
Selinux在這簡單說就需要讓開機程式有對應的權限設定。
1. disabled : 停用模式,遇到有問題的程序會執行。
2. permissive : 寬容模式,遇到有問題的程序會執行,但會顯示警告提醒 (avc dennied)。
3. enforcing : 強制模式,遇到有問題的程序會停止。
動態開關selinux指令
permissive mode:
# setenforce 0
enforcing mode:
# setenforce 1
然後加上
2022年5月16日 星期一
[Android] add_service permission denied issue
[Android] Android 使用adb網路連線debug
或是在AOSP下的build/tools/buildinfo.sh加入
echo "service.adb.tcp.port=5555"
2. PC端
adb connect 192.168.1.58:5555
[Android] Android的映象檔格式 image format
一般原始格式image,檔案內容會完整存入到emmc中,可使用cat command導入到emmc,
例如: cat image.bin> /dev/mmcblk0p1.
2. Sparse image:
因為ext4的image size和partition大小需相同,也就是如果partition size是2G,那image szie也就為2G,因此例用img2simg tool可以將ext4檔案做壓縮動作讓映像檔案變小.一般system, cache, data都是用此格式.
以下是檔案互換的方式:
將sparse image轉換成raw image (ext4 )
system/core/libsparse/simg2img.c
將raw image (ext4 ) 轉換成sparse image
system/core/libsparse/img2simg.c
[Linux] Auto mount 自動掛載 usb disk & SD card
#!/bin/sh
MOUNT_PATH=""
MSG_PATH="/dev/ttyS0"
if [ $1 == "" ]; then
echo "[AutoMount] automount.sh parameter is none" > $MSG_PATH
exit 0
elif [ $1 == "mmcblk0p1" ]; then
MOUNT_PATH="/mnt/sdcard"
else
name=$1
check=${name%[1-9]}
vendor=`cat /sys/block/$check/device/vendor`
if [ $vendor == "ATA" ]; then
MOUNT_PATH="/mnt/hdd/"$name
else
MOUNT_PATH="/mnt/usb/"$name
fi
fi
echo "[AutoMount] mount path : $MOUNT_PATH" >> $MSG_PATH
FORMAT=`/sbin/fdisk -l | grep $1`
OLD_MOUNT_PATH=`mount | grep $MOUNT_PATH`
if [ "$OLD_MOUNT_PATH" == "" ]; then
if [ ! -x $MOUNT_PATH ]; then
mkdir -p $MOUNT_PATH
fi
for token in $FORMAT
do
if [ $token == "FAT32" ]; then
mount -t vfat /dev/$1 $MOUNT_PATH
echo "[AutoMount] mount -t vfat /dev/$1 $MOUNT_PATH" > $MSG_PATH
elif [ $token == "FAT16" ]; then
mount -t vfat /dev/$1 $MOUNT_PATH
echo "[AutoMount] mount -t vfat /dev/$1 $MOUNT_PATH" > $MSG_PATH
elif [ $token == "HPFS/NTFS" ]; then
if [ -f /usr/app/ntfs-3g ]; then
echo "[AutoMount] /usr/app/ntfs-3g /dev/"$1" "$MOUNT_PATH > /var/log/automount/mount.log
export LD_LIBRARY_PATH=/lib/:${LD_LIBRARY_PATH}
/usr/app/ntfs-3g /dev/$1 $MOUNT_PATH
echo "[AutoMount] /usr/app/ntfs-3g /dev/$1 $MOUNT_PATH" > $MSG_PATH
else
mount -t ntfs /dev/$1 $MOUNT_PATH
echo "[AutoMount] mount -t ntfs /dev/$1 $MOUNT_PATH" > $MSG_PATH
fi
elif [ $token == "Linux" ]; then
mount /dev/$1 $MOUNT_PATH
echo "[AutoMount] mount /dev/$1 $MOUNT_PATH" > $MSG_PATH
fi
done
else
umount $MOUNT_PATH
echo "[AutoMount] umount "$MOUNT_PATH > $MSG_PATH
fi
[Linux Kernel] filesystem掛載driver – 以stat硬碟為例
[Linux Porting] Porting SSHD & SFTP
[Linux Porting] PPPoE porting
http://ppp.samba.org/ppp/rp-pppoe-3.10.tar.gz
http://www.roaringpenguin.com/products/pppoe
2.Kernel
CONFIG_PPP=y
CONFIG_PPP_MULTILINK=y
CONFIG_PPP_FILTER=y
CONFIG_PPP_ASYNC=y
CONFIG_PPP_SYNC_TTY=y
CONFIG_PPP_DEFLATE=y
CONFIG_PPP_BSDCOMP=y
CONFIG_PPP_MPPE=y
CONFIG_PPPOE=y
CONFIG_N_HDLC=y
CONFIG_UNIX98_PTYS=y
Refer:
http://tldp.org/HOWTO/PPP-HOWTO/kernel-configuration.html#AEN609
http://rsc.anu.edu.au/General/linux_ppp/ANU-PPP-HOWTO-4.html
http://www.gentoo.org/doc/zh_tw/handbook/handbook-ppc64.xml?part=1&chap=7
[Linux Porting] httpd執行CGI程式
Networking Utilities=>[*] httpd
2. mkdir /www /www/cgi-bin
3. touch /etc/httpd.conf
4. run httpd => httpd -h /www/ -c /etc/httpd.conf
5. CGI程式:有二種方式,一個是用shell script,另一種是用c語言
5.1 shell script
存到/www/cgi-bin/cgi-test
#!/bin/sh
echo “Content-type: text/html"
echo “"
echo “<HTML><HEAD><TITLE>test</TITLE></HEAD>"
echo “<BODY>"
echo “<pre>"
ls
echo “"
echo “</pre>"
echo “</BODY></HTML>"
5.2 C language
#include <stdio.h>
main()
{
printf(“Content-type:text/html\n\n");
printf(“Hello,World!");
}
6. 用瀏覽器執行該二個cgi即可
[Linux] embedded system開機方式
1. initrd (from tftp)
此種是在build kernel時候也把rootfs一起build進來
所以只會有一個檔案
該kernel開機時候會順便把檔案裡的rootfs解壓縮到暫存記憶體
當然關機之後該裡面檔案就又都不見了
boot 192.168.1.254:awaysu/vmlinuz-initrd.img
2. kernel (from tftp) + rootfs (from nfs)
這是都從網路上做開機
一般在debug階段都會用此模式
ifconfig eth0 -auto
boot 192.168.1.254:awaysu/vmlinuz.img 'rootfstype=nfs root=/dev/nfs nfsroot=192.168.1.254:/home/awaysu/nfsrootfs/test rw ip=dhcp'
3. kernel (from storage) + rootfs (from storage)
這是都從flash或是emmc開機
一般在生產階段都會用此模式
ext4:
boot flash0.kernel: "root=/dev/mmcblk0p3 rootfstype=ext4 rw ip=0ff"
ubifs:
boot flash0.kernel: 'ubi.mtd=11 rootfstype=ubifs root=ubi0:rootfs rw ip=off'
[Linux Porting] 建立基本可開機的filesystem
2. 用vi建立一個mkroot.sh,並將下列複製到mkroot.sh裡存檔
echo “creatint rootfs dir……"
mkdir rootfs
cd rootfsecho “making dir : bin dev etc lib proc sbin sys usr"
mkdir bin dev etc lib proc sbin sys usr
# Don’t use mknod ,unless you run this Script as root !
# mknod -m 600 dev/console c 5 1
# mknod -m 666 dev/null c 1 3
echo “making dir : mnt tmp var"
mkdir mnt tmp var
chmod 1777 tmp
mkdir mnt/etc mnt/jffs2 mnt/yaffs mnt/data mnt/temp
mkdir var/lib var/lock var/log var/run var/tmp
chmod 1777 var/tmp
echo “making dir : home root boot"
mkdir home root boot
cd dev
mknod -m 600 console c 5 1;mknod -m 666 null c 1 3
cd ..
cd ..
#=====================================================
echo “copy files from busybox …"
cp -af busybox-1.12.1/_install/* rootfs/
cp -af busybox-1.12.1/examples/bootfloppy/etc rootfs
#=====================================================
echo “copy files from etc …"
cp -af etc/* rootfs/etc
#=====================================================
echo “copy files from lib …"
cp -af lib/* rootfs/lib
#=====================================================
#echo “modify login file form TinyLogin …"
#cd tinylogin-1.4
#make PREFIX=../rootfs/ install
#cd ..
echo “filesystem make finish!"
3. 建立lib目錄,並把需要的library拷貝到該目錄裡
4. 建立etc目錄,並建立以下內容檔案
etc/fstab
proc /proc proc defaults 0 0
none /tmp ramfs defaults 0 0
mdev /dev ramfs defaults 0 0
sysfs /sys sysfs defaults 0 0
etc/inittab
::sysinit:/etc/init.d/rcS
::respawn:/bin/login root
::restart:/sbin/init
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
::shutdown:/sbin/swapoff -a
etc/profile
# /etc/profile: system-wide .profile file for the Bourne shells
echoecho “Processing /etc/profile… "
# no-op
# Set search library path
echo “Set search library path in /etc/profile"
export LD_LIBRARY_PATH=/lib:/usr/lib
# Set user path
echo “Set user path in /etc/profile"
PATH=/bin:/sbin:/usr/bin:/usr/sbin
export PATH
# Set PS1
#注意:ash 除了SHELL變量外,支持\u、\h、\W、\$、\!、\n、\w 、\nnn(ASCII字符對應的八進制數)
#以及\e[xx;xxm (彩色特效)等等!
#而且前面還要多加一個 ‘\’!
echo “Set PS1 in /etc/profile"
export PS1="[$USER@Comtrend]#"
echo “Done"
echo
etc/passwd
root:x:0:0:root:/root:/bin/sh
etc/group
root:x:0:root
etc/shadow
root::13888:0:99999:7:::
etc/mdev.conf
(要有檔案但內容是空的)
#! /bin/sh
echo “———-mount all"
/bin/mount -aecho “———-Starting mdev……"
#/bin/echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s
echo “*********************************************************"
echo " Rootfs 2008/10/15″
echo " Love Linux ! ! ~Awaysu~ "
echo “********************************************************"
5. 下載busybox並解壓縮, http://www.busybox.net/downloads/
(注意版本名稱,mkroot.sh需相同)
6. 進入busybox目錄,使用vi修改Makefile
ARCH = mips
CROSS_COMPILE = mipsel-uclibc-
7. 執行make menuconfig
Mscellaneous Utilities
[ ] readahead
[ ] tasksetLinux System Utilities
[*] Support mounting NFS file systems
Networking Utilities
[ ] ether-wake
[*] Support RPC services
Linux Module Utilities
[ ] Simplified modutils
後面全都要勾
Miscellaneous Utilities
[ ] inotifyd
8. 建立busybox-1.12.1/arch/mips/Makefile
CFLAGS += -mips32 -mtune=mips32
9. 執行make,執行完後再執行make install,完成後會產生_install目錄,請刪除目錄裡的linuxrc檔案.
ld-uClibc-0.9.29.so
libm-0.9.29.so
libuClibc-0.9.29.so
以上我已經包成一個壓縮檔(下載),解開後執行到busybox目錄執行完後再執行make install,會到工作目錄執行make就會產生filesystem到rootfs,再用NFS作為filesystem root執行.
在Bootloader下執行
setenv -p STARTUP “boot -z -elf flash0.kernel1: ‘rootfstype=nfs root=/dev/nfs nfsroot=192.168.168.201:/home/awaysu/rootfs_work/rootfs ip=192.168.168.174 mem=128M'"
http://ccoolloorr.blogspot.com/2008/05/filesystem.html
http://wiki.jk2410.org/wiki/%E5%8A%A0%E5%85%A5Busybox
[Linux Porting] Auto configure
但是含有./configure的則是需要configure去產生Makefile
[root@linux bash-3.2]#
./configure -host=arm-linux CC=arm-linux-gcc CXX=arm-linux-g++ LD=arm-linux-ld AR=arm-linux-ar AS=arm-linux-as
[root@linux bash-3.2]#vi Makefile
修改DESTDIR = ./_install
(一定要修改,否則會蓋到原本的x86 的bash)
[root@linux bash-3.2]#make
[root@linux bash-3.2]#make install
[Linux Porting] Porting NTFS-3G
所以關於source code部分免費的只能使用NTFS-3G
About NTFS-3G:
http://zh.wikipedia.org/zh-hk/NTFS-3G
Download page:
http://www.tuxera.com/community/ntfs-3g-download/
Download:
http://tuxera.com/opensource/ntfs-3g-2010.3.6.tgz
File systems —>
<*> Filesystem in Userspace support
2. Build:
tar zxvf ntfs-3g-2010.3.6.tgz
cd ntfs-3g-2010.3.6
3. 產生Makefile
CC=mipsel-linux-gcc CXX=mipsel-linux-g++ LD=mipsel-linux-ld AR=mipsel-linux-ar AS=mipsel-linux-as RANLIB=mipsel-linux-ranlib NM=mipsel-linux-nm STRIP=mipsel-linux-strip CFLAGS="-mabi=32 -DL_ENDIAN -DTERMIO -O3 -g -Wall" host_os=linux-gnu host=mipsel-mips-linux-gnu ./configure –target=mipsel-unknown-linux-gnu –host=mipsel-unknown-linux-gnu –build=i686-pc-linux-gnu –prefix=
4. Modify file ./include/ntfs-3g/ntfstime.h
#if !defined __timespec_defined && \
((defined _TIME_H && \
(defined __USE_POSIX199309 || defined __USE_MISC)) || \
defined __need_timespec)
# define __timespec_defined 1# include /* This defines __time_t for us. *//* POSIX.1b structure for a time value. This is like a `struct timeval’ but
has nanoseconds instead of microseconds. */
struct timespec
{
__time_t tv_sec; /* Seconds. */
long int tv_nsec; /* Nanoseconds. */
};#endif /* timespec not defined and or need timespec. */
5. Modify file ./src/ntfs-3g.c
// #error “No known timespec member in struct stat!"
/* No known timespec member in struct stat */
struct timespec ts;
ts = ntfs2timespec(ni->last_access_time);
stbuf->st_atime = ts.tv_sec;
//stbuf->st_atimensec = ts.tv_nsec;
ts = ntfs2timespec(ni->last_mft_change_time);
stbuf->st_ctime = ts.tv_sec;
//stbuf->st_ctimensec = ts.tv_nsec;
ts = ntfs2timespec(ni->last_data_change_time);
stbuf->st_mtime = ts.tv_sec;
//stbuf->st_mtimensec = ts.tv_nsec;
#endif
6. make
7.
library產生libntfs-3g/.libs
8. command:
./ntfs-3g /dev/sda1 /mnt/
[Linux Porting] DHCP Client
#!/bin/sh
# udhcpc script edited by Tim Riker <Tim@Rikers.org>
[ -z "$1" ] && echo "Error: should be called from udhcpc" && exit 1
RESOLV_CONF="/etc/resolv.conf"
[ -n "$broadcast" ] && BROADCAST="broadcast $broadcast"
[ -n "$subnet" ] && NETMASK="netmask $subnet"
case "$1" in
deconfig)
/sbin/ifconfig $interface 0.0.0.0
;;
renew|bound)
/sbin/ifconfig $interface $ip $BROADCAST $NETMASK
if [ -n "$router" ] ; then
echo "deleting routers"
while route del default gw 0.0.0.0 dev $interface ; do
:
done
for i in $router ; do
route add default gw $i dev $interface
done
fi
echo -n > $RESOLV_CONF
[ -n "$domain" ] && echo search $domain >> $RESOLV_CONF
for i in $dns ; do
echo adding dns $i
echo nameserver $i >> $RESOLV_CONF
done
;;
esac
exit 0
nameserver 168.95.1.1
/sbin/ifconfig lo 127.0.0.1 up
/sbin/udhcpc -i eth0 -s /etc/udhcpc-script
http://sites.google.com/site/koukailinuxdev/build-usb-linux/create_initrd
[Linux Porting] 小而巧的ssh server (sshd)
不過檔案滿大的
後來發現原來有這個小而巧的sshd server
1.下載:
2.參考[Linux] 移植openssh(ssh server)到MIPS板子上並免密碼 build zlib和openssl
3.解壓縮dropbear,並run it:
CC=mipsel-linux-gcc CXX=mipsel-linux-g++ LD=mipsel-linux-gcc AR=mipsel-linux-ar AS=mipsel-linux-as RANLIB=mipsel-linux-ranlib NM=mipsel-linux-nm STRIP=mipsel-linux-strip CFLAGS="-mabi=32 -DL_ENDIAN -DTERMIO -O3 -g -Wall" host_os=linux-gnu host=mipsel-mips-linux-gnu ./configure –target=mipsel-unknown-linux-gnu –host=mipsel-unknown-linux-gnu –build=i686-pc-linux-gnu –prefix= –with-zlib={zlib的include path}
4.build:
make
5.copy dropbear & dropbearkey to 板子,並run
dropbearkey -t rsa -f /etc/dropbear/dropbear_rsa_host_key
dropbearkey -t dss -f /etc/dropbear/dropbear_dss_host_key
否則會出現
[194] Feb 24 19:58:34 Failed reading ‘/etc/dropbear/dropbear_rsa_host_key’, disabling RSA
[194] Feb 24 19:58:34 Failed reading ‘/etc/dropbear/dropbear_dss_host_key’, disabling DSS
[194] Feb 24 19:58:34 premature exit: No hostkeys available
6.run dropbear
[HTML] 我常用的HTML and Javascript語法
1.預讀圖片
var arraryKeyImg = new Array("img/kb_bq.jpg", "img/kb_bw.jpg", "img/kb_be.jpg");
var loadImg = new Array();
for (i = 0; i != arraryKeyImg.length; i++)
{
loadImg[i] = new Image();
loadImg[i].src = arraryKeyImg[i];
}
2.利用陣列去中控制
var arraryKeyImgID = new Array("key_00", "key_01", "key_02");
for (i = 0; i != 10; i++)
{
document.getElementById(arraryKeyImgID[i]).style.top= 100;
}
<img border="0" src="img/kb_bq.jpg" id="key_00" style="position:absolute">
<img border="0" src="img/kb_bw.jpg" id="key_01" style="position:absolute">
<img border="0" src="img/kb_be.jpg" id="key_02" style="position:absolute">
3.和php一樣抓取參數
function getValue(sArgName) {
var sHref = window.location.href;
var args = sHref.split("?");
var retval = "";
if (args[0] == sHref) {
return retval;
}
var str = args[1];
args = str.split("&");
for (var i = 0; i < args.length; i++) {
str = args[i];
var arg = str.split("=");
if (arg.length <= 1) continue;
if (arg[0] == sArgName) retval = arg[1];
}
return retval;
}
4.設置timer
setTimeout("move();", 1000);
5.讀取網頁時做初始
<body onLoad = "initialize()">
6.動態產生
ShowText1.innerHTML = "<center>";
<div id="ShowText1" style="color: #ffffff; font-size: 16pt; margin-top: 0; margin-bottom: 0">
7.table不稱開
<table style="word-break:break-all>
[Linux] 產生patch
產生patch:
diff -Naur a b > test.patch
使用patch:
patch -p1 < test.patch
2. 使用git:
產生patch:
git init .
git add .
git commit -m " First drop"
git add .
git commit -m "do test patch"
git format-patch HEAD^ --stdout > test.patch
使用patch:
git apply test.patch
[Linux] ffmpeg command
[Linux] UBIFS filesystem
mkfs.ubifs -r ./rootfs -m 8KiB -e 2080768 -c 200 -o rootfs.ubifs
Error: too large LEB size 2080768
這一顆nand flash的info
nand: Micron MT29F32G08CBADAWP
nand: 4096MiB, MLC, page size: 8192, OOB size: 744
brcmnand f0442800.nand: 4096MiB total, 2048KiB blocks, 8KiB pages, 46B OOB, 8-bit, BCH-40 (1KiB sector)
Organization
– Page size x8: 8936 bytes (8192 + 744 bytes)
– Block size: 256 pages (2048K + 186K bytes)
– Plane size: 2 planes x 1064 blocks per plane
– Device size: 32Gb: 2128 blocks
Logical eraseblock size: 2080768 bytes, 2.0 MiB
Total amount of logical eraseblocks: 243 (505626624 bytes, 482.2 MiB)
Amount of available logical eraseblocks: 0 (0 bytes)
Maximum count of volumes 128
Count of bad physical eraseblocks: 2
Count of reserved physical eraseblocks: 38
Current maximum erase counter value: 2
Minimum input/output unit size: 8192 bytes
Character device major/minor: 249:0
Present volumes: 0
最後找到原因,因為舊版linux的ubifs不支援,需要用新版的linux,最後在fedora v21可以執行
sudo mkfs.ubifs -r ./rootfs -m 8KiB -e 2080768 -c 200 -o rootfs.ubifs
sudo ubinize -o mnt/rootfs.ubifs.img -m 8KiB -p 2048KiB -s 8KiB ubinize.cfg
ubinize.cfg:
[ubifs]
mode=ubi
image=rootfs.ubifs
vol_id=0
vol_size=400MiB
vol_type=dynamic
vol_name=rootfs
vol_flags=autoresize
在板子上指令
ubiformat /dev/mtd0 -s 8192 -f rootfs.ubifs.img
ubiattach /dev/ubi_ctrl -m 0
mount -t ubifs ubi0_0 /tmp
[DOS] iperf command
:loop
iperf -s
goto loop
:loop
iperf3 -c {ip} -t 30 -i 3 -u -b 100M
goto loop
[Linux] VLC auto play command
Linux command:
/usr/bin/vlc -v ./DTV2.ts –sout udp:225.1.1.71:30120 –sout-all –ttl 3 –sout-keep –loop &
Windows command:
start “Channel 01″ “C:\Program Files\VideoLAN\VLC\vlc.exe" “D:\demo\out_clip_cut.ts" –sout=#udp{dst=225.
[Linux] 測速隨身碟速度 test usb disk throughput
# 強制 kernel 清理快取
echo 1 > /proc/sys/vm/drop_caches
# Write
echo "dd if=/dev/zero of=/mnt/usb/sda1/test.bin bs=1024 count=716800"
date;dd if=/dev/zero of=/mnt/usb/sda1/test.bin bs=1024 count=716800;sync;date
echo "================================================================="
# 強制 kernel 清理快取
echo 1 > /proc/sys/vm/drop_caches
# Read
echo "dd if=/mnt/usb/sda1/test.bin of=/dev/null bs=1024 count=716800"
date;dd if=/mnt/usb/sda1/test.bin of=/dev/null bs=1024 count=716800;sync;date
[Linux] Makefile
是透過gcc的指令透過參數來產生
gcc -o hello.out -Wall -I./ main.c
由於在複雜的多個程式碼裡只利用gcc指令會變很複雜
所以就有了Makefile的檔案來協助我們來做編譯
以下是二個簡單的Makefile範例
包含了一個執行檔
和另一個執行檔呼叫函式庫Makefile範例
1. 程式的Makefile
main.c
#include "stdio.h"
int main(int argc, char *argv[])
{
printf("Hello World!\n");
return 0;
}
Makefile
CC = gcc
INCLUDE = ./
CFLAG = -Wall
SRC = main.c
EXEC_FILE = hello.out
make_api:
$(CC) -o $(EXEC_FILE) $(CFLAG) -I$(INCLUDE) $(SRC)
clean:
rm -f *.o $(EXEC_FILE)
要注意的是$(CC)前是Tab鍵而非空格
2. Shared Library函式庫的Makefile
extern void ShowHelloWorld();
void ShowHelloWorld();
libtest.c
#include "libtest.h"
#include "stdio.h"
void ShowHelloWorld()
{
printf("Hello World!\n");
}
main.c
#include "libtest.h"
int main(int argc, char *argv[])
{
ShowHelloWorld();
return 0;
}
Makefile
CC = gcc
SRC = ./main.c
INCLUDE = -I./
CFLAG = -Wall -ltest -L./
EXEC_FILE = ./hello.out
LIB = ./libtest.c
LIB_CFLAG = -Wall -fPIC -shared
LIB_NAME = ./libtest.so
all:make_lib make_api
make_api:$(SRC)
$(CC) -o $(EXEC_FILE) $(CFLAG) $(INCLUDE) $(LIB_NAME) $(SRC)
make_lib:$(LIB)
$(CC) -o $(LIB_NAME) $(LIB_CFLAG) $(LIB)
clean:
rm -f *.so $(EXEC_FILE)
另外執行檔要連結函式庫,所以要用到大小寫L的參數
大寫L是表示到時候執行連結函式庫的路徑 (大部分程式的連結都是在/lib下)
小寫l則是lib之後去除.so的檔案名稱, 例如libtest.so就是取test
[Shell Script] 檢查檔案或目錄是否存在
FOLDER=abc
if [ -x $FOLDER ]
then
echo "$FOLDER EXIST"
else
echo "$FOLDER NOT EXIST"
fi
檢查檔案是否存在
FILE=abc
if [ -f $FILE ]
then
echo "$FILE EXIST"
else
echo "$FILE NOT EXIST"
fi
[Linux Kernel] Kernel debug – OOPS
但我都沒有認真看過
因為….真的看不懂
不過上星期上完課之後
終於知道這些數字代表什麼
ssize_t faulty_write (struct file *filp, const char __user *buf, size_t count,
loff_t *pos)
{
/* make a simple fault by dereferencing a NULL pointer */
*(int *)0 = 0;
return 0;
}
當我去執行的時候kernel掛掉
$ echo “1″ > /dev/aaa
Unable to handle kernel NULL pointer dereference at virtual address 00000000
pgd = c3a70000
[00000000] *pgd=33a7e031, *pte=00000000, *ppte=00000000
Internal error: Oops: 817 [#3]
Modules linked in: faulty
CPU: 0 Tainted: G D (2.6.29.2 #2)
PC is at faulty_write+0x10/0x18 [faulty]
LR is at vfs_write+0xc4/0x148
pc : [<bf00009c>] lr : [<c00a5f6c>] psr: a0000013
sp : c3a69f44 ip : c3a69f54 fp : c3a69f50
r10: 400d0948 r9 : c3a68000 r8 : 00000000
r7 : 00000002 r6 : c3a69f78 r5 : 400d3704 r4 : c382cea0
r3 : c3a69f78 r2 : 00000002 r1 : 400d3704 r0 : 00000000
Flags: NzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user
Control: 0000717f Table: 33a70000 DAC: 00000015
Process echo (pid: 882, stack limit = 0xc3a68260)
Stack: (0xc3a69f44 to 0xc3a6a000)
9f40: c3a69f74 c3a69f54 c00a5f6c bf00009c 00000000 c382cec0 c382cea0
9f60: c3a69f78 00000000 c3a69fa4 c3a69f78 c00a60b0 c00a5eb8 00000000 00000000
9f80: 00000000 400d1188 00000002 400d3704 00000004 c0035fa4 00000000 c3a69fa8
9fa0: c0035e00 c00a6074 400d1188 00000002 00000001 400d3704 00000002 4009f9b4
9fc0: 400d1188 00000002 400d3704 00000002 000a8374 00000002 400d0948 00000000
9fe0: 400a491c bec33d74 4009f008 4008accc 20000010 00000001 fffff7f7 fff5ffdf
Backtrace:
[<bf00008c>] (faulty_write+0x0/0x18 [faulty]) from [<c00a5f6c>] (vfs_write+0xc4/0x148)
[<c00a5ea8>] (vfs_write+0x0/0x148) from [<c00a60b0>] (sys_write+0x4c/0x74)
r7:00000000 r6:c3a69f78 r5:c382cea0 r4:c382cec0
[<c00a6064>] (sys_write+0x0/0x74) from [<c0035e00>] (ret_fast_syscall+0x0/0x2c)
r8:c0035fa4 r7:00000004 r6:400d3704 r5:00000002 r4:400d1188
Code: e1a0c00d e92dd800 e24cb004 e3a00000 (e5800000)
—[ end trace 0f24d785ce6e74e6 ]—
Segmentation fault
/ $
因為instruction length是4 byte
faulty_write+0x10/0x18 = > 4 / 6 (6行的第四行錯)
在位置e3a00000 的地方
PC is at faulty_write+0x10/0x18 [faulty]
Code: e1a0c00d e92dd800 e24cb004 e3a00000 (e5800000)
執行mipsel-linux-objdump -S main.o 可以看到組語和程式碼的對應
ssize_t faulty_write (struct file *filp, const char __user *buf, size_t count,
loff_t *pos)
{
8c: e1a0c00d mov ip, sp
90: e92dd800 stmdb sp!, {fp, ip, lr, pc}
94: e24cb004 sub fp, ip, #4 ; 0x4
/* make a simple fault by dereferencing a NULL pointer */
*(int *)0 = 0;
98: e3a00000 mov r0, #0 ; 0x0
9c: e5800000 str r0, [r0]
return 0;
}
所以這樣就可以找到哪一個錯誤!
[C/C++] Socket 範例
Socket Server/Client範例
Code:
Server=>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
int socket_server(int port)
{
int listenfd = 0, connfd = 0;
struct sockaddr_in serv_addr;
char buffer[1024];
listenfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&serv_addr, '0', sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(port);
bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
listen(listenfd, 10);
connfd = accept(listenfd, (struct sockaddr*)NULL, NULL);
memset(buffer, '0', sizeof(buffer));
strcpy(buffer, "I get server message!");
if (write(connfd, buffer, strlen(buffer)) < 0)
{
printf("\n Error : Write Failed \n");
return 1;
}
memset(buffer, '\0', sizeof(buffer));
if (read(connfd, buffer, sizeof(buffer)) < 0)
{
printf("\n Error : Read Failed \n");
return 1;
}
printf("buffer : [%s]\n\n", buffer);
close(connfd);
return 0;
}
int main(int argc, char *argv[])
{
socket_server(5000);
return 0;
}
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
int socket_client(char *ip, int port)
{
int sockfd = 0;
char buffer[1024];
struct sockaddr_in serv_addr;
memset(buffer, '\0',sizeof(buffer));
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("\n Error : Could not create socket \n");
return 1;
}
memset(&serv_addr, '0', sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(port);
if(inet_pton(AF_INET, ip, &serv_addr.sin_addr)<=0)
{
printf("\n inet_pton error occured\n");
return 1;
}
if(connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
printf("\n Error : Connect Failed \n");
return 1;
}
if (read(sockfd, buffer, sizeof(buffer)) < 0)
{
printf("\n Error : Read Failed \n");
return 1;
}
printf("buffer : [%s]\n\n", buffer);
sleep(1);
memset(buffer, '\0', sizeof(buffer));
strcpy(buffer, "I get client message!");
if (write(sockfd, buffer, strlen(buffer)) < 0)
{
printf("\n Error : Write Failed \n");
return 1;
}
close(sockfd);
return 0;
}
int main(int argc, char *argv[])
{
socket_client("127.0.0.1", 5000);
return 0;
}
Result:
[C/C++] Signal範例
Signal範例
Code:
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
static int loop = 1;
void alarm_handler(int a)
{
printf("Alarm!!!\n");
loop = 0;
}
int main(int argc, char *argv[])
{
signal(SIGALRM, alarm_handler);
/* you also can run via "killall -14 xxx" command */
alarm(9);
while(loop)
{
}
printf("Program exit!!!\n");
return 0;
}
Result:
[C/C++] 存取系統時間
存取系統時間
Code:
#include <stdio.h>
#include <time.h>
#include <string.h>
#define BOOL int
#define TRUE 0
#define FALSE -1
#define MAX_LONG_LENGTH 1024
#define MAX_SHORT_LENGTH 128
void get_time_fun(char *p_time)
{
memset(p_time, '\0', strlen(p_time));
struct tm *tm_ptr;
time_t the_time;
time(&the_time);
tm_ptr = localtime(&the_time);
sprintf(p_time, "%02d/%02d/%02d,%02d:%02d:%02d",
tm_ptr->tm_year + 1900,
tm_ptr->tm_mon + 1,
tm_ptr->tm_mday,
tm_ptr->tm_hour,
tm_ptr->tm_min,
tm_ptr->tm_sec);
}
BOOL set_time_fun(char *buffertime)
{
struct tm tm_per;
time_t time1;
int year,month,day,hour,min,sec,flag,len;
year = month = day = hour = min = sec = flag = len = 0;
len = strlen(buffertime);
if(strlen(buffertime) != 19){
return FALSE;
}
flag = sscanf(buffertime,"%d:%d:%d,%d:%d:%d",
&year,
&month,
&day,
&hour,
&min,
&sec);
if(flag != 6){
flag = -1;
}else{
flag = 0;
}
if(year < 1)
flag = -1;
if((month < 1) || (month > 12))
flag = -1;
if((day < 1) || (day > 31))
flag = -1;
if((hour < 0) || (hour > 23))
flag = -1;
if((min < 0) || (min > 59))
flag = -1;
if((sec < 0) || (sec > 59))
flag = -1;
if(flag < 0){
return FALSE;
}
tm_per.tm_year = year - 1900;
tm_per.tm_mon = month - 1;
tm_per.tm_mday = day;
tm_per.tm_hour = hour;
tm_per.tm_min = min;
tm_per.tm_sec = sec;
time1=mktime(&tm_per);
printf("mktime=%ld\n",time1);
if(time1 > 0){
#if __GLIBC_MINOR__ == 31
struct timespec res;
res.tv_sec = time1;
if (clock_settime(CLOCK_REALTIME, &res) ==0)
#else
if(stime(&time1)==0)
#endif
{
return TRUE;
}else{
return FALSE;
}
}else{
return FALSE;
}
}
int main(int argc, char *argv[])
{
char p_time[MAX_SHORT_LENGTH];
get_time_fun(p_time);
printf("Time: %s\n", p_time);
set_time_fun(p_time);
return 0;
}
Result:
[C/C++] 執行參數解析範例
Code:
#include <stdio.h>
#include <unistd.h>
void process_options(int argc, char *argv[])
{
int oc;
char *tmp;
while((oc = getopt(argc, argv, "ngl:")) != -1)
{
switch(oc)
{
case 'n':
printf("My name is Lyong.\n");
break;
case 'g':
printf("Her name is Xxiong.\n");
break;
case 'l':
tmp = optarg;
printf("Our love is %s\n", tmp);
break;
default:
printf("arguments error!\n");
break;
}
}
}
int main(int argc, char *argv[])
{
process_options(argc, argv);
return 0;
}
Result:
2022年5月15日 星期日
[C/C++] 存檔
存檔
Code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#define BOOL int
#define TRUE 0
#define FALSE -1
BOOL save_file_fun(char *filename, char *buffer)
{
int fd = 0;
int length = 0;
BOOL ret = FALSE;
length = strlen(buffer);
if ( (fd = open( filename,
O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) > 0 )
{
if ( write(fd, buffer, length) == length )
ret = TRUE;
else
printf("[ERROR] write %s failed!\n", filename);
if (fd)
close(fd);
sync();
}
else
printf("[ERROR] cannot creat %s!\n", filename);
return ret;
}
int main(int argc, char *argv[])
{
char save[] = "abcde\n12345\n";
save_file_fun("./save.txt", save);
return 0;
}
Result:
會看見save.txt檔案
[C/C++] 一行一行讀檔
一行一行讀檔
Code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#define BOOL int
#define TRUE 0
#define FALSE -1
#define MAX_LONG_LENGTH 1024
#define MAX_SHORT_LENGTH 128
BOOL load_file_fun(char *filename, char **p_content)
{
int fd = -1;
int totalsize = 0;
int readsize = 0;
char buffer[MAX_SHORT_LENGTH];
BOOL ret = FALSE;
if ( (fd = open((char *)filename, O_RDONLY)) > 0 )
{
totalsize = 0;
while( (readsize = read(fd, buffer, MAX_SHORT_LENGTH)) > 0)
totalsize += readsize;
if (totalsize <= 0)
{
printf("[ERROR] %s file size is wrong!\n", filename);
return ret;
}
if (lseek(fd, 0, SEEK_SET) == -1)
{
printf("[ERROR] %s can't seek!\n", filename);
return ret;
}
*p_content = (char*)malloc( ( totalsize + 1) * sizeof(char));
memset(*p_content, '\0', totalsize + 1);
if (*p_content)
{
if(read(fd, *p_content, totalsize) > 0 )
{
ret = TRUE;
}
else
{
printf("[ERROR] %s can't read!\n", filename);
free(*p_content);
}
close(fd);
}
}
else
printf("[ERROR] Open %s fail!\n", filename);
return ret;
}
BOOL load_file_by_line_fun(char *file)
{
char *p_content = NULL;
char *p_tmp = NULL;
char *p_feed = NULL;
char *p_line = NULL;
int len = 0;
BOOL ret = FALSE;
if (load_file_fun(file, &p_content) == TRUE)
{
p_tmp = p_content;
while((p_feed = strpbrk(p_tmp, "\n")))
{
len = p_feed - p_tmp;
p_line = (char*)malloc(len + 1);
memset(p_line, '\0', len + 1);
strncpy(p_line, p_tmp, len);
printf("p_line : %s\n", p_line);
free(p_line);
p_tmp = p_feed + 1;
}
ret = TRUE;
}
if (p_content)
free(p_content);
return ret;
}
int main(int argc, char *argv[])
{
load_file_by_line_fun("/etc/exports");
return 0;
}
Result:
[C/C++] 讀檔
讀檔
Code:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#define BOOL int
#define TRUE 0
#define FALSE -1
#define MAX_LONG_LENGTH 1024
#define MAX_SHORT_LENGTH 128
BOOL load_file_fun(char *filename, char **p_content)
{
int fd = -1;
int totalsize = 0;
int readsize = 0;
char buffer[MAX_SHORT_LENGTH];
BOOL ret = FALSE;
if ( (fd = open((char *)filename, O_RDONLY)) > 0 )
{
totalsize = 0;
while( (readsize = read(fd, buffer, MAX_SHORT_LENGTH)) > 0)
totalsize += readsize;
if (totalsize <= 0)
{
printf("[ERROR] %s file size is wrong!\n", filename);
return ret;
}
if (lseek(fd, 0, SEEK_SET) == -1)
{
printf("[ERROR] %s can't seek!\n", filename);
return ret;
}
*p_content = (char*)malloc( ( totalsize + 1) * sizeof(char));
memset(*p_content, '\0', totalsize + 1);
if (*p_content)
{
if(read(fd, *p_content, totalsize) > 0 )
{
ret = TRUE;
}
else
{
printf("[ERROR] %s can't read!\n", filename);
free(*p_content);
}
close(fd);
}
}
else
printf("[ERROR] Open %s fail!\n", filename);
return ret;
}
int main(int argc, char *argv[])
{
char *p_content = NULL;
if (load_file_fun("/etc/exports", &p_content) == TRUE)
{
printf("%s\n", p_content);
if (p_content)
free(p_content);
}
return 0;
}
Result:
[C/C++] 檢查檔案或資料夾是否存在
檢查檔案或資料夾是否存在
Code:
#include <stdio.h>
#include <unistd.h>
#define BOOL int
#define TRUE 0
#define FALSE -1
#define MAX_LONG_LENGTH 1024
#define MAX_SHORT_LENGTH 128
BOOL is_file_exist_fun(char *filename)
{
int bRet = FALSE;
FILE* fp = fopen(filename, "r");
if (fp)
{
bRet = TRUE;
fclose(fp);
}
return bRet;
}
BOOL is_folder_exist_fun(char *foldername)
{
BOOL bRet = FALSE;
int ret = chdir(foldername);
if (ret == 0)
bRet = TRUE;
return bRet;
}
int main(int argc, char *argv[])
{
BOOL ret = is_file_exist_fun("/etc/exports");
printf("/etc/exports : %s\n", ret==TRUE?"Exist":"Not Exist");
ret = is_folder_exist_fun("/etc/");
printf("/etc/ : %s\n", ret==TRUE?"Exist":"Not Exist");
return 0;
}
Result:
[C/C++] 16進制字串轉數值
16進制字串轉數值
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int strtonum(char *p_input)
{
char *pTmp;
if ( *p_input == '0' )
{
if ( *(p_input + 1) == 'x' ||
*(p_input + 1) == 'X' )
{
pTmp = p_input + 2;
return strtoll( pTmp, NULL, 16 );
}
}
return strtoll( p_input, NULL, 10 );
}
int main(int argc, char *argv[])
{
char val[] = "0x30";
int ret = strtonum(val);
printf("%s = 0x%x\n", val, ret);
return 0;
}
Result:
[C/C++] 程序號碼(process id)
程序號碼(process id)
Code:
#include <stdio.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#define MAX_LONG_LENGTH 1024
#define MAX_SHORT_LENGTH 128
unsigned int get_process_id_fun(char *app_name)
{
DIR *dir_p = NULL;
struct dirent *dir_entry_p = NULL;
char dir_name[MAX_SHORT_LENGTH];
char target_name[MAX_SHORT_LENGTH];
char exe_link[MAX_SHORT_LENGTH];
int target_result = -1;
int result = -1;
dir_p = opendir("/proc/");
while(NULL != (dir_entry_p = readdir(dir_p)))
{
if (strspn(dir_entry_p->d_name, "0123456789")
== strlen(dir_entry_p->d_name))
{
strcpy(dir_name, "/proc/");
strcat(dir_name, dir_entry_p->d_name);
strcat(dir_name, "/");
exe_link[0] = 0;
strcat(exe_link, dir_name);
strcat(exe_link, "exe");
target_result = readlink(exe_link,
target_name, sizeof(target_name)-1);
if (target_result > 0)
{
target_name[target_result] = 0;
if (strstr(target_name, app_name) != NULL)
{
result = atoi(dir_entry_p->d_name);
//printf("getProcessID(%s) :Found. id = %d\n", app_name, result);
closedir(dir_p);
return result;
}
}
}
}
closedir(dir_p);
return result;
}
int main(int argc, char *argv[])
{
printf("smbd id is %d\n", get_process_id_fun("smbd"));
return 0;
}
Result:
[C/C++] 網路IP和MAC位置
網路IP和MAC位置
Code:
#include <stdio.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <linux/netdevice.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <string.h>
#define BOOL int
#define TRUE 0
#define FALSE -1
#define MAX_LONG_LENGTH 1024
#define MAX_SHORT_LENGTH 128
BOOL get_mac_address_fun(char *name, char *mac)
{
BOOL ret = FALSE;
struct ifreq s;
BOOL fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
strcpy(s.ifr_name, name);
if (0 == ioctl(fd, SIOCGIFHWADDR, &s))
{
sprintf(mac, "%02x-%02x-%02x-%02x-%02x-%02x",
(unsigned char) s.ifr_addr.sa_data[0],
(unsigned char) s.ifr_addr.sa_data[1],
(unsigned char) s.ifr_addr.sa_data[2],
(unsigned char) s.ifr_addr.sa_data[3],
(unsigned char) s.ifr_addr.sa_data[4],
(unsigned char) s.ifr_addr.sa_data[5]);
ret = TRUE;
}
return ret;
}
BOOL get_ip_address_fun(char *name, char *ip)
{
int fd;
BOOL ret = FALSE;
struct ifreq ifr;
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd)
{
ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name, name, IFNAMSIZ-1);
ioctl(fd, SIOCGIFADDR, &ifr);
strcpy(ip, inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));
close(fd);
ret = TRUE;
}
return ret;
}
int main(int argc, char *argv[])
{
char ip[MAX_SHORT_LENGTH];
char mac[MAX_SHORT_LENGTH];
get_ip_address_fun("eth0", ip);
get_mac_address_fun("eth0", mac);
printf("ip : %s, mac : %s\n", ip, mac);
return 0;
}
Result:
[C/C++] 目前網路連線狀態
目前網路連線狀態
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/if.h>
#include <linux/sockios.h>
#include <linux/ethtool.h>
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned char u8;
// if_name like "ath0", "eth0". Notice: call this function
// need root privilege.
// return value:
// -1 -- error , details can check errno
// 1 -- interface link up
// 0 -- interface link down.
int get_netlink_status_fun(const char *if_name)
{
int skfd;
struct ifreq ifr;
struct ethtool_value edata;
edata.cmd = ETHTOOL_GLINK;
edata.data = 0;
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name) - 1);
ifr.ifr_data = (char *) &edata;
if (( skfd = socket( AF_INET, SOCK_DGRAM, 0 )) == 0)
return -1;
if(ioctl( skfd, SIOCETHTOOL, &ifr ) == -1)
{
close(skfd);
return -1;
}
close(skfd);
return edata.data;
}
int main(int argc, char *argv[])
{
printf("eth0 : %s\n", get_netlink_status_fun("eth0")==1?"up":"down");
return 0;
}
Result:
[C/C++] 顯示目前mount的狀態
顯示目前mount的狀態
Code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <mntent.h>
#define BOOL int
#define TRUE 0
#define FALSE -1
#define MAX_LONG_LENGTH 1024
#define MAX_SHORT_LENGTH 128
typedef struct mountInfo
{
char dev_name[MAX_SHORT_LENGTH];
char mount_path[MAX_SHORT_LENGTH];
char fs_type[MAX_SHORT_LENGTH];
char attribute[MAX_SHORT_LENGTH];
struct mountInfo *next;
} mountInfoS;
BOOL load_file_fun(char *filename, char **p_content)
{
int fd = -1;
int totalsize = 0;
int readsize = 0;
char buffer[MAX_SHORT_LENGTH];
BOOL ret = FALSE;
if ( (fd = open((char *)filename, O_RDONLY)) > 0 )
{
totalsize = 0;
while( (readsize = read(fd, buffer, MAX_SHORT_LENGTH)) > 0)
totalsize += readsize;
if (totalsize <= 0)
{
printf("[ERROR] %s file size is wrong!\n", filename);
return ret;
}
if (lseek(fd, 0, SEEK_SET) == -1)
{
printf("[ERROR] %s can't seek!\n", filename);
return ret;
}
*p_content = (char*)malloc( ( totalsize + 1) * sizeof(char));
memset(*p_content, '\0', totalsize + 1);
if (*p_content)
{
if(read(fd, *p_content, totalsize) > 0 )
{
ret = TRUE;
}
else
{
printf("[ERROR] %s can't read!\n", filename);
free(*p_content);
}
close(fd);
}
}
else
printf("[ERROR] Open %s fail!\n", filename);
return ret;
}
void get_mount_info_fun(mountInfoS **p_output)
{
char *p_content = NULL;
char *p_tmp = NULL;
char *p_feed = NULL;
char *p_line = NULL;
int len = 0;
int loop = 0;
char *sep = "\t ";
char * pch;
mountInfoS *p_new, *p_first, *p_cur;
p_new = p_first = p_cur = NULL;
if (load_file_fun("/proc/mounts", &p_content) == TRUE)
{
p_tmp = p_content;
while((p_feed = strpbrk(p_tmp, "\n")))
{
len = p_feed - p_tmp;
p_line = (char*)malloc(len + 1);
memset(p_line, '\0', len + 1);
strncpy(p_line, p_tmp, len);
pch = strtok(p_line, sep);
if (pch)
{
p_new = malloc(sizeof(mountInfoS));
memset(p_new, '\0', sizeof(mountInfoS));
loop = 0;
strcpy( p_new->dev_name, pch);
while (pch != NULL)
{
pch = strtok (NULL, sep);
loop++;
if (loop == 1)
strcpy( p_new->mount_path, pch);
else if (loop == 2)
strcpy( p_new->fs_type, pch);
else if (loop == 3)
strcpy( p_new->attribute, pch);
}
if ( p_first == NULL )
{
p_first = p_cur = p_new;
}
else
{
p_cur->next = p_new;
p_cur = p_new;
}
}
free(p_line);
p_tmp = p_feed + 1;
}
}
if (p_content)
free(p_content);
*p_output = p_first;
}
void free_mount_info_fun(mountInfoS *p_input)
{
mountInfoS *p_cur = p_input;
mountInfoS *p_tmp;
p_tmp = p_cur;
while( p_cur )
{
p_tmp = p_cur;
p_cur = p_cur->next;
free( p_tmp );
}
}
int main(int argc, char *argv[])
{
mountInfoS *p_info = NULL;
mountInfoS *p_tmp = NULL;
get_mount_info_fun(&p_info);
if(p_info)
{
p_tmp = p_info;
while(p_tmp)
{
printf("dev_name : %s ", p_tmp->dev_name);
printf("mount_path : %s ", p_tmp->mount_path);
printf("fs_type : %s ", p_tmp->fs_type);
printf("attribute : %s\n", p_tmp->attribute);
p_tmp = p_tmp->next;
}
free_mount_info_fun(p_info);
}
return 0;
}
Result:
[C/C++] 顯示記憶體狀況
說明:
顯示記憶體狀況
Code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/sysinfo.h>
int main(int argc, char *argv[])
{
struct sysinfo sys_info;
if ( sysinfo( &sys_info ) == 0 )
{
printf("Total Ram: %lluM\nFree: %lluM\n",
sys_info.totalram *(unsigned long long)sys_info.mem_unit/1024/1024,
sys_info.freeram *(unsigned long long)sys_info.mem_unit/1024/1024);
}
return 0;
}
Result:
[C/C++] 列出資樂夾裡的資樂夾和檔案
說明:
列出資樂夾裡的資樂夾和檔案
Code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <scsi/scsi.h>
#include <scsi/sg.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
#include <math.h>
#include <fcntl.h>
#include <linux/fs.h>
#include <dirent.h>
#include <string.h>
#include <linux/usbdevice_fs.h>
#define BOOL int
#define TRUE 0
#define FALSE -1
#define MAX_LONG_LENGTH 1024
#define MAX_SHORT_LENGTH 128
#define MAX_MIDDLE_LENGTH 256
typedef enum FILEFOLDER_TYPE
{
ATTRIBUTE_FILE,
ATTRIBUTE_FOLDER,
}FILEFOLDER_TYPE_ENUM;
typedef struct filefolderInfo
{
char pathname[MAX_MIDDLE_LENGTH];
char name[MAX_MIDDLE_LENGTH];
FILEFOLDER_TYPE_ENUM type;
struct filefolderInfo *next;
}filefolderInfoS;
BOOL get_file_folder_list_fun(char *path, filefolderInfoS **p_list)
{
DIR *dir;
struct dirent *p_ptr;
filefolderInfoS *p_first = NULL;
filefolderInfoS *p_current = NULL;
dir =opendir(path);
if (dir == NULL)
return TRUE;
while((p_ptr = readdir(dir))!=NULL)
{
if ( strcmp(p_ptr->d_name, ".") == 0
|| strcmp(p_ptr->d_name, "lost+found") == 0
|| strcmp(p_ptr->d_name, "..") == 0)
{
continue;
}
if (strlen(p_ptr->d_name) > 1 && p_ptr->d_name[0] == '.')
continue;
char pathname[MAX_MIDDLE_LENGTH];
memset(pathname, '\0', MAX_MIDDLE_LENGTH);
struct stat buf;
sprintf(pathname,"%s%s", path, p_ptr->d_name);
stat(pathname, &buf);
filefolderInfoS *p_tmp = malloc(sizeof(filefolderInfoS));
strcpy(p_tmp->pathname, pathname);
strcpy(p_tmp->name, p_ptr->d_name);
p_tmp->next = NULL;
if(S_ISREG(buf.st_mode))
p_tmp->type = ATTRIBUTE_FILE;
else
p_tmp->type = ATTRIBUTE_FOLDER;
//printf("%s, %s, %d\n", p_tmp->pathname, p_tmp->name, p_tmp->type);
if (p_current == NULL)
{
p_first = p_tmp;
p_current = p_tmp;
}
else
{
p_current->next = (filefolderInfoS*)p_tmp;
p_current = p_tmp;
}
}
closedir(dir);
*p_list = p_first;
return TRUE;
}
void free_file_folder_list(filefolderInfoS *p_list)
{
filefolderInfoS *p_current, *p_next;
p_current = p_list;
while(p_current)
{
p_next = (filefolderInfoS*)p_current->next;
free(p_current);
p_current = p_next;
}
}
int main(int argc, char *argv[])
{
filefolderInfoS *p_info = NULL;
filefolderInfoS *p_tmp = NULL;
get_file_folder_list_fun("/etc/", &p_info);
p_tmp = p_info;
if (p_tmp)
{
while(p_tmp)
{
printf("file : %s, %s, %d\n", p_tmp->pathname, p_tmp->name, p_tmp->type);
p_tmp = p_tmp->next;
}
free_file_folder_list(p_info);
}
return 0;
}
Result:
[C/C++] fork範例
說明:
fork範例
Code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
/* fork()類似Thread,他會產生父進程和子進程分成二頭執行,就像是二條Thread. (雖然看似同時間進行,但事實上還是有一個先有一個後.) */
int fork_sample1()
{
pid_t child_pid;
printf("================sample1 getpid: %d ================\n", (int) getpid());
child_pid = fork ();
if (child_pid != 0)
{
// 子進程
printf("sample1 child => getpid() : %d\n", (int) getpid());
printf("sample1 child => child_pid : %d\n", (int) child_pid);
}
else
{
// 父進程
printf("sample1 parent => getpid() : %d\n", (int) getpid());
printf("sample1 parent => getppid() : %d\n", (int) getppid());
}
return 0;
}
/* 當某子進程先終止時(到程式最後return 0), 而父進程還未終止時,會照成程式不正常關閉,所以必須搭配wait來使用. */
int fork_sample2()
{
pid_t child_pid;
int child_status;
printf("================sample2 getpid: %d ================\n", (int) getpid());
child_pid = fork();
if (child_pid != 0)
{
printf("sample2 child => getpid() : %d\n", (int) getpid());
printf("sample2 child => child_pid : %d\n", (int) child_pid);
/* Wait for the child process to complete. */
wait (&child_status);
if (WIFEXITED (child_status))
{
printf ("The child process exited normally, with exit code %d\n", WEXITSTATUS (child_status));
}
else
{
printf ("The child process exited abnormally\n");
}
}
else
{
printf("sample2 parent => getpid() : %d\n", (int) getpid());
printf("sample2 parent => getppid() : %d\n", (int) getppid());
sleep(3);
}
return 0;
}
int main(int argc, char *argv[])
{
//printf("fork_sample1\n");
//fork_sample1();
//sleep(1)
printf("\n\nfork_sample2\n");
fork_sample2();
return 0;
}
Result:
[C/C++] 印出error code的字串
說明:
印出error code的字串
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
extern int errno;
int main(int argc, char *argv[])
{
strtol("0xfffffffff", NULL, 0);
char *err_str = strerror(errno);
printf("Error : [%d], [%s]\n", errno, err_str);
fopen("file.txt", "r");
err_str = strerror(errno);
printf("Error : [%d], [%s]\n", errno, err_str);
return 0;
}
Result:
[C/C++] 利用define來印出debug message
說明:
定義_DEBUG為1時debug message會印出,_DEBUG為0時則不會.
Code:
#include <stdio.h>
#define _DEBUG 1
#ifdef _DEBUG
int (*printf_d)(const char*, ...) = printf;
#else
int printf_d(const char* fmt, ...) {return 0;}
#endif
int main(int argc, char *argv[])
{
printf_d("test\n");
return 0;
}
[C/C++] 使用read/write拷貝檔案範例
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define BOOL int
#define TRUE 0
#define FALSE -1
#define MAX_LONG_LENGTH 1024
#define MAX_SHORT_LENGTH 128
BOOL copyfile_fun(char *src, char *dest)
{
int ret = TRUE;
int len = 0;;
char buffer[MAX_LONG_LENGTH];
int fd1 = open(src, O_RDONLY);
int fd2 = open(dest, O_RDWR|O_CREAT, S_IRWXU);
while((len = read(fd1, buffer, MAX_LONG_LENGTH)) > 0)
{
if (write(fd2, buffer, len) != len)
{
printf("[ERROR] write file %s failed\n", dest);
ret = FALSE;
break;
}
}
if (fd1) close(fd1);
if (fd2) close(fd2);
return ret;
}
int main(int argc, char *argv[])
{
if (copyfile_fun("/etc/exports", "./exports") == TRUE)
printf("[SUCCESS] copy file successfully!\n");
else
printf("[ERROR] copy file failed!\n");
return 0;
}
[C/C++] 存取參數變數範例
存取參數變數範例. 例如setenv/getenv, set property/get property.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#define BOOL int
#define TRUE 0
#define FALSE -1
#define MAX_LONG_LENGTH 1024
#define MAX_SHORT_LENGTH 128
typedef struct ConfigParam
{
char argument[MAX_SHORT_LENGTH];
char option[MAX_SHORT_LENGTH];
struct ConfigParam *next;
}ConfigParamS;
BOOL is_file_exist_fun(char *filename)
{
int bRet = FALSE;
FILE* fp = fopen(filename, "r");
if (fp)
{
bRet = TRUE;
fclose(fp);
}
return bRet;
}
BOOL load_file_fun(char *filename, char **p_content)
{
int fd = -1;
int totalsize = 0;
int readsize = 0;
char buffer[MAX_SHORT_LENGTH];
BOOL ret = FALSE;
if ( (fd = open((char *)filename, O_RDONLY)) > 0 )
{
totalsize = 0;
while( (readsize = read(fd, buffer, MAX_SHORT_LENGTH)) > 0)
totalsize += readsize;
if (totalsize <= 0)
{
printf("[ERROR] %s file size is wrong!\n", filename);
return ret;
}
if (lseek(fd, 0, SEEK_SET) == -1)
{
printf("[ERROR] %s can't seek!\n", filename);
return ret;
}
*p_content = (char*)malloc( ( totalsize + 1) * sizeof(char));
memset(*p_content, '\0', totalsize + 1);
if (*p_content)
{
if(read(fd, *p_content, totalsize) > 0 )
{
ret = TRUE;
}
else
{
printf("[ERROR] %s can't read!\n", filename);
free(*p_content);
}
close(fd);
}
}
else
printf("[ERROR] Open %s fail!\n", filename);
return ret;
}
BOOL save_file_fun(char *filename, char *buffer)
{
int fd = 0;
int length = 0;
BOOL ret = FALSE;
length = strlen(buffer);
if ( (fd = open( filename,
O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) > 0 )
{
if ( write(fd, buffer, length) == length )
ret = TRUE;
else
printf("[ERROR] write %s failed!\n", filename);
if (fd)
close(fd);
sync();
}
else
printf("[ERROR] cannot creat %s!\n", filename);
return ret;
}
void make_default_param_fun(ConfigParamS **p_argu)
{
ConfigParamS *p_new;
p_new = malloc(sizeof(ConfigParamS));
memset(p_new->argument, '\0', sizeof(p_new->argument));
memset(p_new->option, '\0', sizeof(p_new->option));
p_new->next = NULL;
*p_argu = p_new;
}
void get_param_option_fun(char *p_inargu, ConfigParamS **p_outargu)
{
int nindex, nstart, nend;
nindex = nstart = nend = 0;
ConfigParamS *p_first, *p_current, *p_new;
p_first = p_current = p_new = NULL;
void *p_buffer = NULL;
p_buffer = malloc((strlen(p_inargu) + 1) * sizeof(char));
char* p_bufferf = NULL;
p_bufferf = (char *)p_buffer;
strcpy(p_bufferf, p_inargu);
while (nindex < strlen(p_inargu))
{
if (*(p_inargu + nindex) == '=')
{
make_default_param_fun(&p_new);
if (p_first == NULL)
{
p_first = p_current = p_new;
} else {
p_current->next = p_new;
p_current = p_new;
}
nend = nindex;
memcpy(p_current->argument, p_bufferf + nstart, nend - nstart);
nstart = nindex + 1;
}
else if ( *(p_inargu + nindex) == '\n' || *(p_inargu + nindex + 1 ) == '\0')
{
nend = nindex;
memcpy(p_current->option, p_bufferf + nstart, nend - nstart);
nstart = nend + 1;
}
nindex ++;
}
*p_outargu = p_first;
}
void free_param_option_fun(ConfigParamS *p_inargu)
{
ConfigParamS *p_current, *p_next;
p_current = p_inargu;
while(p_current)
{
p_next = p_current->next;
free(p_current);
p_current = p_next;
}
}
BOOL set_config_value_fun(char *file, char *p_argument, char *p_option)
{
char write_buffer[MAX_LONG_LENGTH];
int ret = FALSE;
char *p_buffer = NULL;
ConfigParamS *p_outargu = NULL;
ConfigParamS *p_tmp1 = NULL;
ConfigParamS *p_tmp2 = NULL;
memset(write_buffer, '\0', MAX_LONG_LENGTH);
if (is_file_exist_fun(file) == TRUE)
load_file_fun(file, &p_buffer);
if (p_buffer)
{
get_param_option_fun(p_buffer, &p_outargu);
if (p_outargu)
{
p_tmp1 = p_outargu;
while(p_tmp1)
{
if (strcmp(p_tmp1->argument, p_argument) ==0)
{
ret = TRUE;
strcpy(p_tmp1->option, p_option);
break;
}
p_tmp2 = p_tmp1;
p_tmp1 = p_tmp1->next;
}
if (ret == FALSE)
{
ConfigParamS *p_new = malloc(sizeof(ConfigParamS));
memset(p_new->argument, '\0', sizeof(p_new->argument));
memset(p_new->option, '\0', sizeof(p_new->option));
strcpy(p_new->argument, p_argument);
strcpy(p_new->option, p_option);
p_new->next = NULL;
p_tmp2->next = p_new;
}
p_tmp1 = p_outargu;
while(p_tmp1)
{
strcat(write_buffer, p_tmp1->argument);
strcat(write_buffer, "=");
strcat(write_buffer, p_tmp1->option);
strcat(write_buffer, "\n");
p_tmp1 = p_tmp1->next;
}
save_file_fun(file, write_buffer);
free_param_option_fun(p_outargu);
}
free(p_buffer);
}
else
{
sprintf(write_buffer, "%s=%s\n", p_argument, p_option);
save_file_fun(file, write_buffer);
}
return TRUE;
}
int get_config_value_fun(char *file, char *p_argument, char *p_option)
{
int ret = FALSE;
char *p_buffer = NULL;
ConfigParamS *p_outargu = NULL;
ConfigParamS *p_tmp1 = NULL;
load_file_fun(file, &p_buffer);
if (p_buffer)
{
get_param_option_fun(p_buffer, &p_outargu);
if (p_outargu)
{
p_tmp1 = p_outargu;
while(p_tmp1)
{
if (strcmp(p_tmp1->argument, p_argument) ==0)
{
ret = TRUE;
strcpy((char *)p_option, p_tmp1->option);
break;
}
p_tmp1 = p_tmp1->next;
}
free_param_option_fun(p_outargu);
}
free(p_buffer);
}
return ret;
}
int main(int argc, char *argv[])
{
char value[MAX_SHORT_LENGTH];
set_config_value_fun("./test.conf", "AA", "123");
set_config_value_fun("./test.conf", "BB", "456");
set_config_value_fun("./test.conf", "CC", "456");
if (get_config_value_fun("./test.conf", "BB", (char *)value) == TRUE)
printf("BB : %s\n", value);
else
printf("[ERROR] get failed!\n");
return 0;
}