在 LInux Ubuntu 要如何 Complie C (使用 gcc)或者是 C++ 檔案(使用 g++)
gcc 的用法相當地多,在此只講一行的方法。就是
gcc –o output_file_name source.c
如果沒有加”-o output_file_name”這個選項的話,預設輸出會是 a.out
一般的 C 副檔名可以取名為 .c
如 hello.c
1 2 3 4 5
| #include <stdio.h>
int main() {
printf("%s","Hello World!!");
} |
在 console 下打
gcc hello.c
會出現一些錯誤 , 例如找不到 stdio.h
利用 sudo find / -name stdio.h 尋找也會找不到檔案
因此需要下載 sudo apt-get install g++
complie 可打
gcc hello_c.c -o hello_c
另外一個範例為 c++
hello_cc.cc
1 2 3 4 5 6 7
| #include <iostream>
using namespace std;
int main(int argc,char *argv[])
{
cout << "Hello, world!\n";
return 0;
} |
c++ 則要使用 g++ 來 complie
$ g++ -Wall hello.cc -o hello
或是分成兩行
$ g++ -Wall -c hello.cc
$ g++ hello.o (should use g++)
一個完整的範例包含 Makefile
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| main.cc
#include <iostream>
using namespace std;
// Output in print.cc
extern void Output(void);
int main(void)
{
Output();
return 0;
}
print.cc
#include <iostream>
using namespace std;
void Output(void)
{
cout << "print one line!" << endl;
}
Makefile
# Makefile for printline
#
# GNU g++
#
# use gcc here for usual C Code
CC = g++
# Put the parameters for compiling the c code here
# ( -O2 is a kind of Optimization parameter )
CFLAGS = -O2
# Object Files
# ( make will automatically search the corresponding .c or .cc file for
# compiling )
OBJ = main.o print.o
all: printline
clean:
rm -f *.o core printline
printline: $(OBJ)
$(CC) $(CFLAGS) -o printline $(OBJ) |
在 Windows 上 Trace Code 可以使用 Source Insight
但在 Linux 上如果要 Trace Code 是否有這麼好用的軟體?
搜尋Google大神,答案或許應該是肯定的
(操作起來可能沒有 SOurce Insight 這麼方便)
Vim……
安裝可以操考以下幾個 Blog
1.http://c9s.blogspot.com/2007/07/vim-taglist-plugin.html
2.http://andrewtw.wordpress.com/2006/12/25/gvim-%E5%A5%BD%E7%8E%A9%E8%80%B6%EF%BD%9E/
3.http://walkingice.twbbs.org/blog/?p=167
4.http://nixchun.pixnet.net/blog/post/21765036
當然也可以參考 Vim 官網
http://vim-taglist.sourceforge.net/installation.html
只要照著步驟安裝都可以成功
1 2 3 4 5 6 7 8 9 10 11
| #KERNELDIR ?= /usr/src/linux
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
obj-m += hidsample2.o
all:
make -C $(KERNELDIR) M=$(PWD) modules
clean:
make -C $(KERNELDIR) M=$(PWD) clean |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
| /* -------------------------------------------------------------------------- */
/* ----- err_t FFTransform(sig_t *,unsigned long,vector_t *,vector_t *) ----- */
/* -------------------------------------------------------------------------- */
/*
* Performs FFT on "signal" x:
*
* - Truncate or pad with zeros if npts != in->n
* - Copy truncated/padded x->n to real part and set imaginary part to 0.0
* - Call mixfft [fft()]
* - Write phase and modulus to the output vectors
*
* Either modul or phase can be NULL if one is not
* interested in this result.
*
* Note that "signal" may not be a signal, but it can be
* LPCOEFF vector hidden in a sig_t structure!
*/
err_t FFTransform(sig_t *x,unsigned long npts,vector_t *modul,vector_t *phase)
{
int i,j;
float tmp[MAX_FFT_SIZE];
/*
* Check that (nearly) all is OK!
*/
if(npts > MAX_FFT_SIZE) {
gerror(FFT_LENGTH_ERR,"FFTransform(): FFT length too large (npts= %d, max= %d)",
npts,MAX_FFT_SIZE);
return(FFT_LENGTH_ERR);
}
if(frexp((double)npts,&i) != (double)0.5) {
gerror(FFT_LENGTH_ERR,"FFTransform(): FFT length (%d) is not a power of two",
npts);
return(FFT_LENGTH_ERR);
}
if(x->n == 0 || npts == 0) {
gerror(ZERO_LENGTH_WARN,"FFTransform(): zero length signal (nb. samples= %d, npts= %d)",
x->n,npts);
DONE;
}
if(modul)
if(modul->n < npts/2) {
gerror(OUT_SIZE_ERR,"FFTransform(): not enough memory allocated to module vector");
return(OUT_SIZE_ERR);
}
if(phase)
if(phase->n < npts/2) {
gerror(OUT_SIZE_ERR,"FFTransform(): not enough memory allocated to phase vector");
return(OUT_SIZE_ERR);
}
if(x->n > npts)
gerror(FFT_TRUNC_WARN,"FFTransform(): signal length greater than FFT order (truncating)");
/*
* Copy signal to buffers and apply fft
*/
for(i=0;in && is[i];
for(;i< npts;i+=2,j++) {
if(modul)
modul->data[j]=(param_t)sqrt(tmp[i]*tmp[i]+tmp[i+1]*tmp[i+1]);
if(phase)
phase->data[j]=(param_t)atan(tmp[i+1]/tmp[i]);
}
if(modul)
modul->n=npts/2;
if(phase)
phase->n=npts/2;
DONE;
} |
因為之前的 Code Display PlugIn 不好用
另外又找了一個 SyntaxHighlighter Evolved
試用看看如何
目前的 Code Display 設定 Default 為 Close 的
需要點 <> 這個標示才會顯示出 Code
與以前的 PlugIn 相比,比較不影響 Blog 的美觀度
終於開始寫 Mini2440 的 Module Driver
第一個學習的階段就是寫一個 Leds Module Driver
以下部分為 Driver Source
[sourcecode]
/*
** [2009.02.21][JUSTKU]
** hello.c - Demostrating the module_init() and module_exit() macros.
** This is prefered over using init_module() and cleanup_module()
*/
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/arch/regs-gpio.h>
#define DRIVER_AUTHOR "JUSTKU"
#define DRIVER_DESC "Mini2440 Led Char Driver"
#define DEVICE_NAME "MiniLeds"
#define SUCCESS 0
#define NUM_LEDS 4
/*
** Prototypes
*/
static int __init leds_init(void);
static void __exit leds_exit(void);
static int device_open(struct inode *, struct file *);
static int device_release(struct inode *, struct file *);
static ssize_t device_read(struct file *, char *, size_t, loff_t *);
static ssize_t device_write(struct file *, const char *, size_t, loff_t *);
static int device_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
/*
** Global variables are declared as static, so are global within the file.
*/
static int Major; /* Major number assigned to our device driver */
static int Device_Open = 0 ;/* Is device open? */
static struct file_operations fops = {
.read = device_read,
.write = device_write,
.open = device_open,
.ioctl = device_ioctl,
.release = device_release,
};
static int _gLedStatus[NUM_LEDS]={0,0,0,0};
static unsigned long _gLedTable[] = {
S3C2410_GPB5,
S3C2410_GPB6,
S3C2410_GPB7,
S3C2410_GPB8,
};
static unsigned int _gLedCfgTable[]={
S3C2410_GPB5_OUTP,
S3C2410_GPB6_OUTP,
S3C2410_GPB7_OUTP,
S3C2410_GPB8_OUTP,
};
/* Get rid of taint message by declareing code as GPL */
MODULE_LICENSE("Dual BSD/GPL");
static int __init leds_init(void)
{
int i;
Major = register_chrdev(0, DEVICE_NAME, &fops);
if(Major < 0)
{
printk(KERN_INFO "Registering MiniLeds char device failed with %dn", Major);
return Major;
}
printk(KERN_INFO "The process is "%s" (pid %i)n",current->comm, current->pid);
printk(KERN_INFO "The driver major number is %dn", Major);
printk(KERN_INFO "Create a dev file withn");
printk(KERN_INFO "mknod /dev/%s c %d 0′.n", DEVICE_NAME, Major);
printk(KERN_INFO "Try various minor numbers, Try to cat and echo to the device file");
devfs_mk_cdev(MKDEV(Major,0), S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP,DEVICE_NAME);
for( i = 0 ; i < 4 ; i++ )
{
s3c2410_gpio_cfgpin(_gLedTable[i], _gLedCfgTable[i]);
s3c2410_gpio_setpin(_gLedTable[i], 1);
}
return SUCCESS;
}
static void __exit leds_exit(void)
{
/*
** Unregister the device
*/
int ret = unregister_chrdev(Major, DEVICE_NAME);
if(ret < 0)
printk(KERN_INFO "Error in unregister_chardev: %dn", ret);
devfs_remove(DEVICE_NAME);
}
/*
** Method Implement
*/
/*
** Called with a process tries to open the device file, like
** "cat /dev/MiniLeds’
*/
static int device_open(struct inode *inode, struct file *file)
{
static int counter = 0;
if(Device_Open)
return -EBUSY;
Device_Open++;
try_module_get(THIS_MODULE);
return SUCCESS;
}
/*
** Called when a process closes the device file
*/
static int device_release(struct inode *unode, struct file *file)
{
Device_Open–;
/*
** Decrement the usage count, or else once you open the file,
** you’ll never get rid of the module
*/
module_put(THIS_MODULE);
return 0;
}
/*
** Called when a process, which already opened the dev file, attempts to
** read from it.
*/
static ssize_t device_read(struct file *filep, /* see include/linux/fs.h */
char *buff, /* buffer to fill with data */
size_t length, /* length of the buffer */
loff_t *offset)
{
/*
** Number of bytes actually read to the buffer
*/
int bytes_read = sizeof(_gLedStatus);
copy_to_user(buff, (char*)_gLedStatus, bytes_read);
return bytes_read;
}
/*
** Called when a proces, which already opened the dev file, attempts to
** write from it.
*/
static ssize_t device_write(struct file *filep, /* see include/linux/fs.h */
const char *buff, /* buffer to fill with data */
size_t length, /* length of the buffer */
loff_t *offset)
{
/*
** Number of bytes actually written to the buffer
*/
printk(KERN_ALERT "Sorry, this operation isn’t supported.n");
return -EINVAL;
}
static int device_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
switch(cmd)
{
case 0:
case 1:
if(arg>4)
{
return -EINVAL;
}
s3c2410_gpio_setpin(_gLedTable[arg],!cmd);
return 0;
default:
return -EINVAL;
}
}
module_init(leds_init);
module_exit(leds_exit);
/*
** Who wrote this module ?
** What does this module do ?
*/
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
/*
** This module uses /dev/MINIHELLO. The MODULE_SUPPORT_DEVICE macro might
** be used in the future to help automatic configuration of modules, but is
** currently unused other than for documentation purpose.
*/
MODULE_SUPPORTED_DEVICE("MINIHELLO");
[/sourcecode]
TEST CODE 的部分為
[sourcecode]
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
int main(int argc, char **argv)
{
int fd;
int vLed;
int vVal;
fd = open("/dev/MiniLeds", 0);
if(fd<0)
{
printf("Can not open devicen");
exit(1);
}
while(1)
{
printf("Please select led number(0~3) to run programn");
scanf("%d", &vLed);
printf("Please set led %d On/Offn");
scanf("%d", &vVal);
ioctl(fd, vVal, vLed);
if(vLed==4)
break;
}
close(fd);
return 0;
}
[/sourcecode]
記得要將 Leds-play 關掉阿!!
/etc/rc.d/init.d/leds stop
TestMiniLeds 記得要先 chmod +x TestMiniLeds
以下為 Log Recoed
[root@FriendlyARM /Mini2440]# ls
TestMiniLeds hello hello.ko miniLeds.ko
[root@FriendlyARM /Mini2440]# insmod miniLeds.ko
The process is “insmod” (pid 524)
The driver major number is 253
Create a dev file with
mknod /dev/MiniLeds c 253 0′.
Try various minor numbers, Try to cat and echo to the device file[root@FriendlyARM /Mini2440]#
[root@FriendlyARM /Mini2440]# ./TestMiniLeds
Please select led number(0~3) to run program
1
Please set led 1 On/Off
1
Please select led number(0~3) to run program
0
Please set led 0 On/Off
1
Please select led number(0~3) to run program
2
Please set led 2 On/Off
0
Please select led number(0~3) to run program
在之前的文章有提過如何在 Linux build 一個 hello 的 char driver
但這個如果 char driver module 要在 Mini2440 上使用
必須要以 arm-linux-gcc build 才可以
但卻又不是使用 arm-linux-gcc -o hello hello.c 就可以
經過 Google 的 search 後
寫了一個 Makefile 來完成 Build 的步驟
KERNELDIR=/usr/src/FriendlyARM/kernel-2.6.13
PWD := $(shell pwd)
CC =/usr/local/arm/3.4.1/bin/arm-linux-gcc
obj-m := hello.o
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
rm -rf *.o *~ core.depend .*.cmd *.ko *.mod.c .tmp_versions
重點是要設定 KERNEL 的 INCLUDE SOURCE
Build 成功後會產生一個 hello.ko
將 hello.ko 利用 zModem 傳到 Mini2440 上 (command line 打 rz 接收)
再 insmod hello.ko
可利用 lsmod 來查看
最近看到 Youtube 不錯的影片
研究了一下想要抓下 FLV 檔
1.
可以透過 Web 方式下載,這裡有 36 種不同的方法
http://blog.kusos.com/2007/10/72.html
2.
透過軟體
推薦可以使用 WinAVI FLV Converter 下載 FLV
並可以轉換成各種格式
使用 WinAVI 跟 IPOD 可說是絕配的組合阿
hello.c
[sourcecode]
/*
** [2009.02.21][JUSTKU]
** hello.c - Demostrating the module_init() and module_exit() macros.
** This is prefered over using init_module() and cleanup_module()
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/sched.h>
#define DRIVER_AUTHOR "JUSTKU"
#define DRIVER_DESC "Mini2440 Hello Char Driver"
/* Get rid of taint message by declareing code as GPL */
MODULE_LICENSE("Dual BSD/GPL");
static int __init hello_init(void)
{
printk(KERN_INFO "Hello, worldn");
printk(KERN_INFO "The process is "%s" (pid %i)n",current->comm, current->pid);
return 0;
}
static void __exit hello_exit(void)
{
printk(KERN_INFO "Goodbye, cruel worldn");
}
module_init(hello_init);
module_exit(hello_exit);
/*
** Who wrote this module ?
** What does this module do ?
*/
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
/*
** This module uses /dev/MINIHELLO. The MODULE_SUPPORT_DEVICE macro might
** be used in the future to help automatic configuration of modules, but is
** currently unused other than for documentation purpose.
*/
MODULE_SUPPORTED_DEVICE("MINIHELLO");
[/sourcecode]
Makefile
[sourcecode]
obj-m += hello.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
[/sourcecode]
以下是 Log
kernel@kernel-desktop:~/driver-example$ make
make -C /lib/modules/2.6.24-19-generic/build M=/home/kernel/driver-example modules
make[1]: Entering directory `/usr/src/linux-headers-2.6.24-19-generic’
Building modules, stage 2.
MODPOST 1 modules
make[1]: Leaving directory `/usr/src/linux-headers-2.6.24-19-generic’
kernel@kernel-desktop:~/driver-example$
kernel@kernel-desktop:~/driver-example$ modinfo hello.ko
filename: hello.ko
description: Mini2440 Hello Char Driver
author: JUSTKU
license: Dual BSD/GPL
srcversion: B2A9A23E4AAE15500DEBADE
depends:
vermagic: 2.6.24-19-generic SMP mod_unload 586
kernel@kernel-desktop:~/driver-example$ sudo insmod hello.ko
kernel@kernel-desktop:~/driver-example$ sudo rmmod hello
kernel@kernel-desktop:~/driver-example$ dmesg
[35554.786547] Hello, world
[35554.786561] The process is “insmod” (pid 7777)
[35639.186938] Goodbye, cruel world
以上可以在 UBuntu 上面順利運行
上篇我們寫了一個 Led 的測試程式
但發現在開機後,Led 就會自動在閃呀閃的!
研究了一下
發現是在 Linux 開機時會去啟動一個 Leds 的 Service
打開 /etc/inittab_
[root@FriendlyARM /etc]# ls
boa group inetd.conf_ mime.types pointercal resolv.conf
fstab host.conf init.d mtab profile services
ftpchroot hosts inittab_ passwd protocols sysconfig
ftpusers inetd.conf login.defs passwd_ rc.d
[root@FriendlyARM /etc]# vi inittab_
inittab_ 是開機會自動被執行的一個 sh
內容如下
#
# inittab This file describes how the INIT process should set up
# the system in a certain run-level.
#
# Author: Miquel van Smoorenburg,
# Modified for RHS Linux by Marc Ewing and Donnie Barnes
#
# Default runlevel. The runlevels used by RHS are:
# 0 - halt (Do NOT set initdefault to this)
# 1 - Single user mode
# 2 - Multiuser, without NFS (The same as 3, if you do not have networking)
# 3 - Full multiuser mode
# 4 - unused
# 5 - X11
# 6 - reboot (Do NOT set initdefault to this)
#
# System initialization.
::sysinit:/etc/init.d/rcS
::askfirst:/sbin/getty 115200 console
~
~
我們可以看得出來當 System Initial 時會自動執行 /etc/init.d/rcS
打開 :/etc/init.d/rcS
/etc/rc.d/init.d/netd start
echo ” ” > /dev/vc/0
echo “Starting networking…” > /dev/vc/0
usleep 300000
/etc/rc.d/init.d/httpd start
echo ” ” > /dev/vc/0
echo “Starting web server…” > /dev/vc/0
usleep 300000
/etc/rc.d/init.d/leds start
echo ” ” > /dev/vc/0
echo “Starting leds service…” > /dev/vc/0
echo ” ”
usleep 300000
/sbin/ifconfig lo 127.0.0.1
/sbin/ifconfig eth0 192.168.1.230 up
/bin/qtopia &
echo ” ” > /dev/vc/0
echo “Starting Qtopia, please waiting…” > /dev/vc/0
/bin/hostname -F /etc/sysconfig/HOSTNAME
以下這行是啟動 leds 的 service
/etc/rc.d/init.d/leds start
再打開 /etc/rc.d/init.d/leds
[sourcecode]
#!/bin/sh
base=led-player
# See how we were called.
case 1; in start
/sbin/$base &
;;
stop)
pid=`/bin/pidof $base`
if [ -n pid ]; then
kill -9 $pid
fi
;;
esac
exit 0
[/sourcecode]
以上看得出來當有參數 start 時會去執行 /sbin/led-player
stop 時會去執行 kill 的動作
[root@FriendlyARM vc]# /bin/pidof led-player
283
所以如果要啟動或是停止 service 的寫法可參考此部分