Lời nói đầu.
Ngày nay,với sự phát triển của các linh kiện điện tử và công nghiệp sản xuất vi
mạch,hệ thống Linux nhúng đã xuất hiện hầu như ở khắp mọi khía cạnh trong cuộc
sống, từ các thiết bị điện tử dân dụng thông thường đến những thiết bị mạng cao cấp.
Nếu so sánh các thiết bị này với các hệ thống nhúng truyền thống thì mức độ phức tạp
và khả năng đáp ứng cao hơn rất nhiều.Việc tích hợp hệ điều hành lên hệ thống nhúng
làm đơn giản hóa quá trình nghiên cứu và phát triển các sản phẩm, rút ngắn thời gian
và chi phí xây dựng hệ thống vì các hệ thống này được thừa hưởng những tính chất ưu
việt của một hệ điều hành nói chung cũng như Linux nói riêng, như tính ổn định, nhỏ
gọn, thực thi nhanh và có khả năng can thiệp sâu vào phần cứng.
Hơn thế nữa, cùng với cộng đồng sử dụng Linux rộng lớn trên khắp thế giới và
các phần mềm mã nguồn mở đa dạng làm cho việc phát triển hệ thống Linux nhúng trở
thành một chiến lược được các công ty lựa chọn hàng đầu. Nhờ phần mểm mã nguồn
mở khiến cho việc tùy biến một ứng dụng phù hợp yêu cầu trở nên dễ dàng hơn. Nhận
thức được tầm quan trọng này, đề tài thực hiện việc tìm hiểu Linux cho các hệ thống
nhúng và các ứng dụng trên hệ thống nhúng. Phần cứng đề cập đến trong đề tài là kit
XUP Virtex-II Pro Development Syste Xilinx (XUPV2P). Cụ thể sẽ tiến hành việc cài
đặt hệ điều hành MontaVista Linux – một gói Linux chuyên dành cho các hệ thống
nhúng – lên kiến trúc vi xử lý PowerPC405 được tích hợp trên kit XUPV2P. Đồng thời
xây dựng các ứng dụng chạy trên hệ điều hành này. Ứng dụng trọng tâm là giao tiếp
truyền dữ liệu qua TCP/IP, với server là ứng dụng chạy trên hệ thống nhúng đã cài đặt
và client là ứng dụng chạy trên hệ điều hành Windows. Ứng dụng cung cấp khả năng
upload, download dữ liệu và có phân quyền với giao diện người dùng thân thiện.
Mục lục
Chương 1 Linux trên hệ thống nhúng 7
1.1Khái niệm cơ bản .7
1.2Hệ điều hành Linux nhúng (Embedded Linux) .8
1.3Real-time Linux .9
1.4Phân loại hệ thống Linux nhúng 9
1.4.1 Kích thước .10
1.4.2 Khả năng đáp ứng theo thời gian 11
1.4.3 Khả năng kết nối .11
1.4.4 Khả năng tương tác với người dùng 12
1.5Kiến trúc tổng quát của một hệ thống Linux nhúng 12
1.5.1 Khối Data Acquisition .13
1.5.2 Khối Control 14
1.5.3 Khối System management .15
1.5.4 Khối User interface .16
1.6Tổng quan về kernel của Linux/Unix 16
1.6.1 Mô hình process/kernel: 16
1.6.2 Thi hành một process 18
1.6.3 Tái thực thi các process .18
1.6.4 Không gian địa chỉ các tiến trình: .20
1.6.5 Sự đồng bộ hóa và những vùng then chốt: 21
1.6.6 Việc giao tiếp tín hiệu và liên tiến trình 22
1.6.7 Quản lí tiến trình: 23
1.6.8 Quản lý bộ nhớ 25
1.6.9 Device Drivers .28
Chương 2 Thiết kế một hệ thống Linux nhúng .30
2.1Phần cứng hỗ trợ 30
2.1.1 Kiến trúc CPU .30
2.1.2 Bus và các chuẩn giao tiếp 31
2.1.3 Các thiết bị lưu trữ .31
2.1.4 Kết nối mạng .32
2.2Các công cụ phát triển .33
2.3Chọn lựa và biên dịch Linux kernel 34
2.3.1 MontaVista Linux .37
2.3.2 uClinux 38
2.3.3 Cấu hình kernel .38
2.4Xây dựng hệ thống thư mục gốc (root filesystem) 40
2.4.1 Hệ thống tập tin (File Systems) .40
2.4.2 Các thư mục trên Linux .40
Chương 3 Kit XUPV2P và gói phần mềm phát triển của Xilinx 44
3.1Kiến trúc phần cứng của Kit XUPV2P 44
3.1.1 Tổng quan 44
3.1.2 Khối FPGA Virtex II Pro 46
3.1.3 System ACE 47
3.1.4 Ethernet adaptor 58
3.1.5 Cấu trúc MicroBlaze .69
3.1.6 PowerPC 78
3.2Các gói phần mềm phát triển của Xilinx .85
3.2.1 Xilinx EDK 86
3.2.2 BSB Winzard (Base System Builder) .86
Chương 4 Thiết kế hệ thống nhúng dùng Linux 88
4.1Những công cụ thực hiện .88
4.1.1 Hardware .88
4.1.2 Software .88
4.2Kiểm tra kit XUPV2P 89
4.3Thiết kế phần cứng cho hệ thống với Xilinx BSB 90
4.3.1 Cấu hình sử dụng bộ xử lý PowerPC 90
4.3.2 Cấu hình các thiết bị ngoại vi 93
4.3.3 Cấu hình phần mềm .96
4.4Thiết lập môi trường biên dịch chéo 98
4.5Biên dịch nhân MontaVista Linux trên kiến trúc PowerPC405 100
4.5.1 Tải kernel source và chuẩn bị driver .100
4.5.2 Cấu hình nhân 102
4.5.3 Tạo ACE file cấu hình cho FPGA và nạp ảnh kernel .105
4.5.4 Quá trình khởi động Linux trên kit XUPV2P .107
4.6Xây dựng cấu trúc thư mục gốc cho hệ điều hành 108
Chương 5 Lập trình ứng dụng Server chạy trên hệ thống nhúng và Client trên Windows .
5.1Mô tả hệ thống file server của uClinux .112
5.2Cấu trúc lập trình: 113
5.3Lưu đồ thiết kế: 114
5.4Chương trình File Client MP3 trên Visual C++ MFC: .115
5.4.1 Giới thiệu : .115
5.4.2 Chương trình File Client MP3: .116
5.4.3 Giao diện File Client MP3: .Error! Bookmark not defined.
Chương 6 Giới hạn của đề tài và hướng phát triển trong tương lai .118
6.1Tổng kết những phần đã thực hiện 118
6.2Giới hạn .118
6.3Hướng phát triển trong tương lai .118
138 trang |
Chia sẻ: lvcdongnoi | Lượt xem: 4237 | Lượt tải: 1
Bạn đang xem trước 20 trang tài liệu Đề tài Nghiên cứu linux trên hệ thống nhúng và ứng dụng, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
quá trình biên dịch kết xuất rất nhiều thông báo nên lưu thông
báo để theo dõi là rất cần thiết. Trong quá trình biên dịch phải đảm bảo kết nối internet
vì kịch bản này sẽ tiến hành download gcc và thư viện glibc trên internet.. Ta có thể
theo dõi tiến trình này bằng các xem nội dung của file log
$ less demo-ppc405.log
Nhấn Shift + G để đọc file log trong khi nó vẫn được truy xuất bởi kịch bản.
Tùy thuộc vào tốc độ máy tính và tốc độ kết nối internet, quá trình này sẽ mất khoảng
60 phút không kể đến thời gian download. Sau khi hoàn thành, thư mục
/home//xupv2p/crosstool-0.43/downloads sẽ có 6 tập tin được tải về:
$ ls /home//xupv2p/crosstool-0.43/downloads
binutils-2.16.1.tar.bz2 gcc-4.1.0.tar.bz2 glibc-2.3.6.tar.bz2
gcc-3.3.6.tar.bz2 gdb-6.5.tar.bz2 linux-2.6.15.4.tar.bz2
$ ls /opt/crosstool
gcc-3.4.4-glibc-2.3.3
4.5 Biên dịch nhân MontaVista Linux trên kiến trúc PowerPC405
4.5.1 Tải kernel source và chuẩn bị driver
Trước khi bắt đầu biên dịch nhân, chúng ta phải cấu hình các thông số cho nhân
phù hợp với kit XUPV2P và các thiết bị ngoại vi của nó. Ở đây chúng ta sẽ dùng nhân
MontaVista Embedded Linux 3.1 vì nó hỗ trợ đầy đủ các phần cứng của kit XUPV2P,
bao gồm SystemACE Controller, Ethernet MAC và các GPIO.
SVTH: Trần Quang Thuận – Phan Bá Minh. - 100 -
Nghiên cứu Linux trên hệ thống nhúng và ứng dụng.
Tải source của kernel MontaVista Linux phiên bản 2.41 từ website nhà cung
cấp thông qua rsync2
$ cd /home//xupv2p/
$ mkdir mvistappc_2_4_devel
$ cd mvistappc_2_4_devel
$ rsync -avz –-delete rsyns:\\source.mvista.com\linuxppc_2_4_devel
Khi đã tải thành công source của MontaVista Linux, chúng ta sẽ thay đổi các
file cấu hình và driver cho phù hợp với kit XUPV2P, MontaVista được thiết kế có thể
chạy trên nhiều hệ thống nhúng khác nhau chứ không phải chỉ có kit XUPV2P.
Copy các file BSP đã tạo ra ở phần cấu hình phần cứng vào source của kernel,
cụ thể là thư mục arch và thư mục drivers trong thư mục TARGET_DIR, vào
mvistappc_2_4_devel. Ở bước này cần một công cụ để có thể chuyển dữ liệu từ một
máy Windows sang Linux, và đối với máy host sử dung Fedora Core 7 thì công cụ này
đã được tích hợp sẵn.
Thay đổi trong arch/ppc/boot/simple/Makefile vì có một chút sai sót khi biên
dịch từ lần thứ 2, để tránh thông báo “File not found”. Mỗi lần biên dịch sẽ copy (cp)
chứ không move (mv) kernel image.
zImage-EMBEDDED: zvmlinux
cp zvmlinux ../images/zImage.$(END)
Nếu bắt đầu biên dịch ở bước này, chúng ta sẽ gặp loạt thông báo
“UNDEFINED REFERENCE”. Cần thay thế drivers OCP FIFO của bus hệ thống
bằng version mới hơn. Cấu hình ban đầu của kernel sử dụng driver cũ, từ phiên bản
EDK 8.1i đã thay đổi nên ta cần thay đổi một chút để có thể biên dịch nhân sử dụng
Ethernet MAC driver. Thay đổi trong arch/ppc/platforms/xilinx_ocp/Makefile
xilinx_ocp-objs += xbasic_types.o xdma_channel.o xdma_channel_sg.o \
1 MontaVista chỉ cung cấp source code của phiên bản 2.4. Các nhân phiên bản 2.6 phải mua lisence từ
nhà cung cấp.
2 Rsync là một tiện ích để truyền các file thường xuyên cập nhật trên Linux, thường là source code của
các phần mềm mã nguồn mở. Phát triển bởi Wayne Davison.
SVTH: Trần Quang Thuận – Phan Bá Minh. - 101 -
Nghiên cứu Linux trên hệ thống nhúng và ứng dụng.
xipif_v1_23_b.o xpacket_fifo_v2_00_a.o \
xpacket_fifo_l_v2_00_a.o xversion.o
Thay đổi trong arch/ppc/platforms/xilinx_ocp/xilinx_syms.c
#include "xpacket_fifo_v2_00_a.h"
EXPORT_SYMBOL(XPacketFifoV200a_Initialize);
EXPORT_SYMBOL(XPacketFifoV200a_Read);
EXPORT_SYMBOL(XPacketFifoV200a_SelfTest);
EXPORT_SYMBOL(XPacketFifoV200a_Write);
Khi biên dịch và thử nghiệm trên kit, việc cuối cùng ta làm trong bước này là
download một bản vá của file drivers/block/xilinx_sysace/adaptor.c để tránh hiện lỗi
treo hệ thống khi mount RFS, lỗi này do được cộng đồng phát triển Linux trên
PowerPC vá.
> Partition check:
> xsysacea:
Có thể download bản vá tại địa chỉ:
embedded/attachments/20060816/cd559042/attachment.obj
4.5.2 Cấu hình nhân
Tiếp theo chúng ta sẽ cấu hình các module trong nhân Linux, di chuyển vào thư
mục chứa source code của kernel:
$ cd /home//xupv2p/mvistappc_2_4_devel
$ make menuconfig
Lệnh trên sẽ gọi giao diện cấu hình nhân Linux ở chế độ cấu hình bằng các
menu đơn giản.
SVTH: Trần Quang Thuận – Phan Bá Minh. - 102 -
Nghiên cứu Linux trên hệ thống nhúng và ứng dụng.
Hình 4-19: Chế độ cấu hình nhân bằng các menu đơn giản
Tuy nhiên chúng ta vẫn có thể cấu hình bằng
$ make config
Bằng các trả lời các option, Y (Yes) hoặc N (No) để sử dụng hay không dùng
từng module ta cũng có thể cấu hình cho nhân. Tuy nhiên sẽ rất khó khăn đối với
người mới làm quen vì nó không cho phép quay lại thực hiện các thay đổi, muốn thay
đổi cấu hình, chúng ta phải chạy $ make config một lần nữa. Chúng ta cấu hình nhân
Linux sử dụng các module như sau:
Code maturity level options --->
[*] Prompt for development and/or incomplete code/drivers
Platform Support --->
(40x) Processor Type
(Xilinx-ML300) Machine Type
[*] Math emulation
(UART0) TTYS0 device and default console
General Setup --->
[*] Default bootloader kernel arguments string:
"console=ttyS0,9600 root=/dev/xsysace/disc0/part3 rw"
[*] Networking support
[*] Sysctl support
[*] System V IPC Block Devices
* Xilinx on-chip System ACE
SVTH: Trần Quang Thuận – Phan Bá Minh. - 103 -
Nghiên cứu Linux trên hệ thống nhúng và ứng dụng.
* Loopback device support
* Network block device support
Networking options --->
[*] Packet socket
[*] Unix domain sockets
[*] TCP/IP networking
[*] IP: kernel level autoconfiguration
[*] IP: DHCP support
Network device support --->
[*] Network device support
Ethernet (10 or 100Mbit) --->
[*] Ethernet (10 or 100Mbit)
[*] Xilinx on-chip ethernet
Character devices --->
[*] Standard/generic (8250/16550 and compatible UARTs) serial support
[*] Support for console on serial port
File systems --->
[*] /proc file system support
[*] /dev file system support (EXPERIMENTAL)
[*] Automatically mount at boot
[*] Second extended fs support
Nếu như từ quá trình cài đặt môi trường biên dịch chéo chúng ta đã log out khỏi
terminal thì phải export lại các biến môi trường, chỉ đường dẫn đến trình biên dịch
chéo cho PowerPC405:
$ export TARGET=powerpc-405-linux-gnu
$ export PREFIX=/opt/crosstool/gcc-3.4.4-glibc-2.3.3/${TARGET}
$ export PATH=${PREFIX}/bin:${PATH}
Và cuối cùng là tạo ra image cho nhân Linux bằng
$ make dep && make zImage
Quá trình biên dịch nhân chỉ mất khoảng 5 phút trên hệ thống AMD Athlon 64
X2 Dual-core Processor, với máy host chạy trên phần mềm giả lập Vmware. Ảnh của
kernel sẽ được lưu trữ ở arch/ppc/boot/images/zImage.elf.
SVTH: Trần Quang Thuận – Phan Bá Minh. - 104 -
Nghiên cứu Linux trên hệ thống nhúng và ứng dụng.
4.5.3 Tạo ACE file cấu hình cho FPGA và nạp ảnh kernel
Trước hết để dễ quản lý, tạo những thư mục ACE, thư mục ELF chứa file kernel
của Linux đã tạo và GenACE chứa file tùy chọn .opt trong thư mục chứa project ban
đầu (Xilinx EDK project) như trong ảnh minh họa.
Hình 4-20: Thư mục phát triển
Tạo file có tên GenACE.opt trong thư mục GenACE có nội dung như sau:
-jprog
-board xupv2p
-target ppc_hw
-hw implementation/system.bit
-elf ELF/zImage.elf
-ace ACE/system.ace
Copy script tcl mặc định của Xilinx từ /data/xmd vào thư
mục GenACE và thêm một số định nghĩa cho kit XUPV2P:
# Production XUPV2P
set xupv2p(jtag_chain_options) "-configdevice devicenr 1 idcode
0x1127e093 irlength 14 partname xc2vp30 -debugdevice devicenr 1 cpunr 1"
set xupv2p(jtag_fpga_position) 1
set xupv2p(jtag_devices) "xc2vp30"
SVTH: Trần Quang Thuận – Phan Bá Minh. - 105 -
Nghiên cứu Linux trên hệ thống nhúng và ứng dụng.
Cuối cùng là copy ảnh của kernel đã biên dịch từ máy host vào thư mục ELF.
Bây giờ chúng ta sẽ tạo ra file ACE chứa trên CF card. Từ máy cài EDK, gọi chương
trình Xilinx Xygwin từ Startmenu hoặc chạy file /bin/nt/xbash.exe.
Chuyển đến thư mục chứa project:
$ cd d:\\thesis\\xupv2p
Và tiếp tục chạy xmd để bắt đầu quá trình tạo ra file ACE
$ xmd -tcl GenACE/xupGenACE.tcl –opt GenACE/GenACE.opt
Quá trình này có kết xuất như trong hình :
Hình 4-21: Cú pháp và thông báo khi tạo ACE file
Trong quá trình chạy, Xygwin có thể báo lỗi file elf corrupted. Vấn đề này được
khắc phục bằng các nâng cấp EDK 9.1i bằng các bản sevices pack, được cung cấp ở
website của Xlinx. Khi đã tạo ra file ACE, việc tiếp theo là phải lưu trữ nó trên một
DOS partion định dạng theo chuẩn của Xilinx của CF card. Việc chia CF card thành
SVTH: Trần Quang Thuận – Phan Bá Minh. - 106 -
Nghiên cứu Linux trên hệ thống nhúng và ứng dụng.
các partitions sẽ được thực hiện trên máy host. Sử dụng lệnh sau để biết tên ở đĩa CF
card.
$ fdisk -l
Ở đây sẽ mình họa với CF card được trỏ ở /dev/sdb. Lần lượt phân vùng các
partitions và format như sau :
Partition 1, FAT16, kích thước 256MB
Partition 2, Linux Swap, kích thước 256MB
Partition 3, Linux, kích thước là phần còn lại của CF card
$ sudo mkdosfs –v –F 16 –R 1 -s 64 –n XLNX_ACE /dev/sdb1
$ sudo mkswap /dev/sdb2
$ sudo mke2fs –L XLNX_RFS /dev/sdb3
Công việc cuối cùng là copy file system.ace đã tạo ra ở trên vào phân vùng
FAT16 của CF card. Chạy TeraTerm và chọn baud rate 9600, kiểm tra phần cứng của
kit, bật nguồn vào theo dõi boot log trên TeraTerm.
4.5.4 Quá trình khởi động Linux trên kit XUPV2P
Mặc dầu quá trình khởi động từ bên ngoài nhìn vào của Linux không mấy khó
khăn, hầu hết mọi người dung đều công nhận những tiến trình diễn ra từ thời điểm
công tắc nguồn được bật cho đến khi màn hình đăng nhập hiện ra. Việc không cần tìm
hiểu quá trình khởi động của Linux không làm ảnh hưởng đến người dùng có thể sử
dụng hệ điều hành hay không. Tuy nhiên, đối với việc phát triển một phần mềm mã
nguồn mở hay một người phát triển phần cứng thì hiểu được quá trình boot là rất quan
trọng. Từ đó, ta có thể thấy được sự khác biệt giữa quá trình khởi động Linux của một
bo mạch chủ trong máy tính desktop/laptop và kit XUPV2P.
Khi bo mạch chủ được khởi động, nó phải biết được địa chỉ của hệ điều hành.
Chip BIOS (Basic Input Output System.) có nhiệm vụ cung cấp địa chỉ này cho bo
mạch chủ. Chip BIOS sẽ truy xuất một vị trí đặc biệt trên đĩa cứng (hoặc một vị trí
khác được chỉ định trong quá trình cài đặt BIOS) gọi là boot sector. Tuy nhiên, boot
sector có không gian lưu trữ không đủ lớn cho hệ điều hành. Nhưng chúng ta có thể
tìm được địa chỉ của hệ điều hành dễ dàng hơn khi trong boot sector chứa boot loader
SVTH: Trần Quang Thuận – Phan Bá Minh. - 107 -
Nghiên cứu Linux trên hệ thống nhúng và ứng dụng.
(GRUB, LILO…). Khi boot loader được thực thi, nó sẽ tìm đến địa chỉ chính xác của
của hệ điều hành và tải vào bộ nhớ của hệ thống.
Tuy nhiên, trên kit XUPV2P, rõ ràng chúng ta không hề thấy chip BIOS.
Nhưng những khái niệm cơ bản luôn giúp ích trong qua trình tìm hiểu, mấu chốt nằm
ở khối logic được đặt trong chip Xilinx SystemACE sẽ thực hiện chức năng như chip
BIOS. Chip Xilinx System ACE thực sự là một thiết bị thông minh. Nó lần lượt tải bit
stream cấu hình phần cứng đến FPGA và sau đó là ảnh ELF (Executable and Linking
Format: file thực thi chạy trên bộ xử lý PowerPC)của hạt nhân (kernel) lên SDRAM.
Khi kernel được tải lên bộ nhớ chính, quá trình boot được thực thi giống như
các hệ thống Linux khác (trên máy tính và trên hệ thống nhúng) giao tiếp qua console
bằng cổng nối tiếp. Hạt nhân đầu tiên sẽ thực thi chuỗi lệnh để cấu hình cổng nối tiếp.
Linux/PPC load: console=ttyS0,9600 root=/dev/xsysace/disc0/part3 rw
Tiếp theo sau đó kernel sẽ tải tất cả những cấu hình driver đã được biên dịch
trước đó và khởi tạo cho mỗi thiết bị. Ở đây có một chú ý là hầu hết các hệ điều hành
không bao giờ tham chiếu đến địa chỉ thực, Linux sẽ tái lập các thiết bị xuất nhập qua
bộ nhớ ảo bằng cách sử dụng hàm ioremap(). Kết quả của quá trình này được kết xuất
trong kernel boot log. (Xem đầy đủ boot log trong phụ lục)
Interrupt Controller remapping:
Xilinx INTC #0 at 0x41200000 mapped to 0xFDFFE000
UART_16550A remapping:
ttyS00 at 0xfdfff003 (irq = 29) is a 16550A
Xilinx SystemACE remapping:
System ACE at 0x41800000 mapped to 0xD1000000, irq=30, 1000944KB
Xilinx Ethernet_MAC controller remapping:
eth0: Xilinx EMAC #0 at 0x40C00000 mapped to 0xD1013000, irq=31
4.6 Xây dựng cấu trúc thư mục gốc cho hệ điều hành
Khi đã biên dịch được kernel và khởi động hệ thống từ file system.ace. Ở thời
điểm này chúng ta vẫn chưa thể login vào shell và thực hiện một số lệnh cơ bản của
mọi hệ điều hành Linux như các lệnh quản lý file và thư mục. Chúng ta sẽ thực hiện
bằng các sử dụng gói phần mềm BusyBox. Phiên bản sử dụng trong demo là gói
SVTH: Trần Quang Thuận – Phan Bá Minh. - 108 -
Nghiên cứu Linux trên hệ thống nhúng và ứng dụng.
busybox-1.2.0 được tải từ website
và giải nén vào thư mục /home//xupv2p và bắt đầu cấu hình:
$ cd /home//xupv2p/busybox-1.2.0
$ make menuconfig
Câu lệnh trên cũng giống như phần chọn cấu hình nhân Linux, sẽ xuất hiện giao
diện cấu hình bằng các menu đơn giản.
Hình 4-22: Chọn lựa các tiện ích trong BusyBox
Việc lựa chọn các tiện ích trong BusyBox tùy theo vào mục đích sử dụng hệ
thống, kích thước của file binary cũng sẽ tăng theo số lượng các tiện ích. Vì vậy, phần
này chỉ đưa ra chọn lựa các tiện ích cần thiết:
Busybox Settings --->
Build Options --->
[*] Do you want to build BusyBox with a Cross Compiler?
(powerpc-405-linux-gnu-) Cross Compiler prefix
Installation Options --->
(/xupv2p/RFS) BusyBox installation prefix
Coreutils --->
cat, chmod, chown, date, echo, ls, mkdir, mv, stat, whoami
Console Utileties --->
clear
Editors --->
vi
SVTH: Trần Quang Thuận – Phan Bá Minh. - 109 -
Nghiên cứu Linux trên hệ thống nhúng và ứng dụng.
Init Utilities --->
Init, Support reading an inittab file, poweroff, halt, and reboot
Login/Password Management Utilities --->
adduser, deluser, getty, login, passwd, su, sulogin
Linux System Utilities -->
Swaponoff, umount,
Networking Utilities --->
hostname, httpd, ifconfig, inetd, netstat, ping, route, udhcp
Process Utilities --->
ps,
Shells --->
Choose your default shell (ash) --->
--- ash
System Logging Utilities --->
Syslogd
Công việc tiếp theo là tạo một cấu trúc thư mục gốc của Linux, để trong quá
trình boot, hệ thống sẽ mount và thực hiện các lệnh được cấu hình trong thư mục /etc.
Hiểu được cấu trúc của thư mục gốc và ngôn ngữ script mạnh mẽ, chúng ta có thể tự
viết một script để thực hiện công việc này. Ở đây sẽ sử dụng script mkrootfs của
Wolfgang Klingauf, tải từ địa chỉ thực hiện
một số thay đổi cho phù hợp với đường dẫn:
# cross compiler prefix
CC=powerpc-405-linux-gnu
# gcc & glibc versions chosen for PPC Linux
GCC_VER=gcc-3.4.4
GLIBC_VER=glibc-2.3.3
# embedded linux kernel version
PPC_KERNEL_VER=2.4.26
# development directory
DEV_DIR=/home//xupv2p
# where the root file system should be placed
RFS=${DEV_DIR}/RFS
# RFS TARBALL filename (if wanted)
RFS_TAR=`basename $RFS`
SVTH: Trần Quang Thuận – Phan Bá Minh. - 110 -
Nghiên cứu Linux trên hệ thống nhúng và ứng dụng.
# HTTP server root
HTTP_ROOT=/var/www/localhost/htdocs
# Location of GNUMAKE source files
GNUMAKE_SRC=${DEV_DIR}/make-3.81
# Install location for GNUmake
GNUMAKE_INS=${RFS}/usr
# embedded linux kernel sources
PPC_KERNEL_SRC=${DEV_DIR}/mvistappc_2_4_devel
# location of PPC kernel modules
PPC_KERNEL_MOD=${PPC_KERNEL_SRC}/images/modules-${PPC_KERNEL_VER}
# location of busybox
BUSYBOX=${DEV_DIR}/busybox-1.2.0
# Location of gcc and glibc tools
TOOLS_DIR=${DEV_DIR}/powerpc-405-linux-gnu-tools
# location of *non-prefixed* tool-chain binaries which will be copied to the RFS
TARGET_PREFIX=/opt/crosstool/${GCC_VER}-${GLIBC_VER}/${CC}/${CC}
# cross build tools directory
BUILD_TOOLS=${DEV_DIR}/crosstool-0.42/build/${CC}/${GCC_VER}-
${GLIBC_VER}/${GLIBC_VER}
Trong script này sẽ thực hiện những công việc như sau:
1. Tạo các thư mục
2. Copy thư viện Glibc sang thư mục RFS
3. Biên dịch BusyBox và chứa trong thư mục RFS
4. Thay đổi quyền truy xuất và sở hữu của các file, thư mục trong RFS
Chạy script mkrootfs.sh để bắt đầu quá trình:
$ cd /home//xupv2p/mkrootfs/
$ sh mkrootfs.sh
Kết thúc quá trình này, chúng ta copy nội dung của thư mục RFS sang phân
vùng thứ 3 (Ext2) của CF card, lặp lại quá trình kiểm tra, boot và theo dõi boot log,
nếu như mọi bước đều hoàn thành chính xác, ta sẽ có boot log giống trong phần phụ
lục.
SVTH: Trần Quang Thuận – Phan Bá Minh. - 111 -
Nghiên cứu Linux trên hệ thống nhúng và ứng dụng.
Chương 5 Ứng dụng chạy trên hệ thống nhúng
5.1 Mô tả hệ thống file server
Ứng dụng file server lấy ý tưởng tạo ra 1 trình duyệt file bên trong CF card.
Thông qua Internet chúng ta sẽ truyền hoặc nhận file từ trình khách client.Chúng ta
hãy xem hình sau:
Sơ đồ khối của Socket Server-Client MP3
ETHERNET PORT
SDRAM
CF CARD
/VAR/MP3
Request
Send/Receive
SERVE CLIENT
HARD DISK
SDRAM
ETHERNET
PORT
Kit XUP PC
IP,PORT
INTERNET
User,Passwo
d
SVTH: Trần Quang Thuận – Phan Bá Minh. - 112 -
Nghiên cứu Linux trên hệ thống nhúng và ứng dụng.
5.2 Mô tả giải thuật thiết kế
Chương trình Server có 3 phần chính: Tạo Socket, Download và Upload. Tùy
thuộc vào yêu cầu của client Download hoặc Upload mà server sẽ lựa chọn cho từng
module nhất định.
Nếu client yêu cầu Download: Trước tiên Server phải chạy trình duyệt file
trong CF card và gửi danh sách các file mp3 cho client. Sau đó Server đợi client truyền
lại cho tên file mp3 mà client muốn download. Lúc này Server sẽ tìm kiếm đúng file
đó, đo chiều dài file, rồi lại cho client chiều dài file mp3 này và tiếp tục chờ. Sau khi
client đã nhận được chiều dài file, Client sẽ gửi yêu cầu bắt đầu truyền. Server sẽ
truyền từng Gói 1000 byte cho client cho đến khi truyền hết. Trong quá trình truyền
file bất cứ gói 1000 byte nào bị hư thì client sẽ yêu cầu Server truyền lại cho đến khi
truyền 1000 byte đó thành công thì thôi.
Nếu client yêu cầu Upload: Server sẽ yêu cầu client gửi tên file và chiều dài file
mà client muốn upload. Sau khi nhận được đầy đủ Server phải tạo 1 file trống trong
buffer của mình và gửi lại cho client yêu cầu bắt đầu truyền file. Client sẽ truyền cho
Server từng gói 1000 byte. Công việc của Server là sau khi nhận đủ từng gói 1000 byte
nếu thành công thì sẽ ghi từ buffer vào trong CF card. Sau đó lại tiếp tục công việc cho
đến khi hoàn tất dung lượng của file mp3 mà client yêu cầu.
SVTH: Trần Quang Thuận – Phan Bá Minh. - 113 -
Nghiên cứu Linux trên hệ thống nhúng và ứng dụng.
5.3 Lưu đồ thiết kế
Hình 5-1: Lưu đồ thiết kế
5.4 Biên dịch ứng dụng chạy trên hệ thống Linux nhúng
Hiển nhiên là đoạn chương trình phải được biên dịch để có thể chạy trên target
là PowerPC405. Vì vậy chúng ta phải biên dịch nó thành file nhị phân thực thi trên
kiến trúc PowerPC405. Việc này rất đơn giản với máy host đã xây dựng môi trường
biên dịch chéo ở phần trên, chúng ta chỉ cần nhập những dòng lệnh sau để export các
biến môi trường và bắt đầu biên dịch (chú ý: phải chuyển đến thư mục chứa source
code trước)
$ export TARGET=powerpc-405-linux-gnu
SVTH: Trần Quang Thuận – Phan Bá Minh. - 114 -
Nghiên cứu Linux trên hệ thống nhúng và ứng dụng.
$ export PREFIX=/opt/crosstool/gcc-3.4.4-glibc-2.3.3/${TARGET}
$ export PATH=${PREFIX}/bin:${PATH}
$ powerpc-405-linux-gnu-gcc -o mp3 mp3.c
Sau quá trình này, ta copy file nhị phân mp3 vào thư mục /bin trên Root
filesystem của hệ thống, tức là phân vùng thứ 3 của CF card để có thể gọi thực thi
ngay từ shell của máy target.
5.5 Chương trình File Client MP3 trên Visual C++ MFC
5.5.1 Giới thiệu
Khi PC giao tiếp với Kit XUP chúng ta có nhiều cách để thực hiện.Ví dụ : lập
trình Socket, lập trình Java, hay lập trình HTML để tạo 1 file client MP3 chạy trên
máy PC. Với các ngôn ngữ lập trình như Pascal, C, C++, java, … Trong khuôn khổ
của đề tài này, với phần đã lập trình Socket cho file Server MP3 chạy trên Kit
XUPV2P nên chúng ta chọn phương pháp lập trình Socket cho file client MP3 chạy
trên máy PC. Lập trình Socket có thể chạy trên nhiều môi trường hệ điều hành khác
nhau. Linux hay Windows đều có thể chạy được Socket. Tuy nhiên, chúng ta mong
muốn file client MP3 phải có giao diện dễ sử dụng và hiệu quả.
Trong môi trường Linux, chúng ta hoàn toàn có thể lập trình Socket được,
nhưng giao diện trong môi trường này là giao diện terminal bằng các dòng lệnh shell
của Linux. Như vậy người sử dụng phải bắt buộc phải biết vài kiến thức cơ bản về lập
trình Linux. Ngoài ra, việc thực thi môt chương trình với toàn câu lệnh sẽ gây ra khó
khăn và nhàm chán. Với những khuyết điểm về giao diện trên, chúng ta không nên
chọn lập trình Socket trong môi trường Linux.
Để giải quyết vấn đề của giao diện của File Client MP3 chạy trên máy PC với
những điều kiện đòi hỏi: lập trình Socket, giao diện đẹp và dễ sử dụng, chương trình
có thể chình sửa dễ và không cồng kềnh với các hàm giao diện phức tạp và quan trọng
hơn là giao diện phải tạo ra sự tương tác với người sử dụng. Vì vậy chúng ta chọn lựa
phần mềm Visual C++ MFC là phù hợp nhất đối với yêu cầu của đề tài.
Microsoft cung cấp công cụ lập trình Visual C++ MFC đã có sẵn các hàm tạo ra
cửa sổ. Ứng dụng cũng như tự xử lý các thông báo và tự vẽ. MFC cố gắn không thể
hiện những công việc nội bộ phức tạp làm cho việc tạo ra một ứng dụng chung trở nên
SVTH: Trần Quang Thuận – Phan Bá Minh. - 115 -
Nghiên cứu Linux trên hệ thống nhúng và ứng dụng.
dễ dàng hơn. Bốn cơ sở chủ yếu cho ứng dụng MFC là: việc tạo một cửa sổ, việc hiểu
biết về các lớp MFC, gửi thông báo cho một cửa sổ và việc vẽ bên trong cửa sổ. Ngôn
ngữ chính là C++. Ngoài ra Visual còn hỗ trợ mạnh về thư viện chuẩn C, C++ và thư
viện về các chuẩn giao tiếp Internet.
5.5.2 Chương trình File Client MP3
Trong project này có 2 phần quan trọng nhất là :Download module và Upload
module.Cà 2 phần này đều hướng vào việc tạo ra Socket và nhận hoặc truyền dữ liệu
giữa Server(Linux Monta Vista PowerPC) và Client(Windows PC).
Hình 5-2: Giao diện MP3 File client
SVTH: Trần Quang Thuận – Phan Bá Minh. - 116 -
Nghiên cứu Linux trên hệ thống nhúng và ứng dụng.
Hình 5-3: Demo của thiết kế
SVTH: Trần Quang Thuận – Phan Bá Minh. - 117 -
Nghiên cứu Linux trên hệ thống nhúng và ứng dụng.
Chương 6 Giới hạn của đề tài và hướng phát triển trong
tương lai
6.1 Tổng kết những phần đã thực hiện
Tìm hiểu quá trình thiết lập, cài đặt một hệ thống Linux trên các hệ thống
nhúng với các kiến trúc phần cứng, chuẩn giao tiếp và lưu trữ khác nhau.
Tìm hiểu nhân Linux ở mức độ ứng dụng, có khả năng cấu hình biên dịch và
debug.
Lập trình và thử nghiệm các ứng dụng hệ điều hành Linux trên hệ thống nhúng,
lập trình giao tiếp socket giữa Linux và Windows. Tối ưu hóa tốc độ đường truyền.
6.2 Giới hạn
Trước mắt hệ thống của chúng em có những giới hạn sau:
• Giao diện của chương trình còn đơn giản và khó sử dụng đối với người sử
dụng
• Chưa sử dụng hết các tính năng phần cứng trên Kit XUP Virtex-II Pro
Development System
• Một số driver phần cứng chưa tương thích với hệ điều hành.
6.3 Hướng phát triển trong tương lai
Đi sâu hơn tìm hiểu nắm vững nhân Linux. Thử nghiệm với các nhân Linux
khác nhau trên các kiến trúc softcore CPU như Altera NIOS hay hardcore CPU phổ
biến như dòng ARM hay H8. Đây là 2 dòng rất phổ biến trong các thiết bị như router
hay các máy tính nhỏ, điện thoại di động. Đặc biệt là dòng H8 vì giá thành rẻ và đã
được hổ trợ bởi dự án uClinux.
Mở rộng hệ thống có khả năng giao tiếp thông qua môi trường Internet mà
không chỉ giới hạn trong một mạng LAN. Nếu có thể sử dụng được những kỹ thuật
SVTH: Trần Quang Thuận – Phan Bá Minh. - 118 -
Nghiên cứu Linux trên hệ thống nhúng và ứng dụng.
port forward và NAT (network address translation), việc định tuyến các gói tin ra
ngoài mạng Internet là hoàn toàn khả thi.
Trong quá trình làm đề tài, chúng em đã có ý tưởng và đọc các tài liệu để có thể
xây dựng một giao diện điều khiển web base, thông qua đó có thể sử dụng các tài
nguyên phần cứng, quản lý và điều khiển cả hệ thống bằng giao diện web, thông qua
giao thức http. Công cụ mã nguồn mở Webmin có thể khả dụng vì đáp ứng được
những yêu cầu như trên.
SVTH: Trần Quang Thuận – Phan Bá Minh. - 119 -
Nghiên cứu Linux trên hệ thống nhúng và ứng dụng.
Tài liệu tham khảo
[1] Nguyễn Phương Lan, Hoàng Đức Hải, Lập trình Linux, NXB Lao động –
Xã hội.
[2] Nguyễn Đình Tê, Tự học lập trình Visual C++ MFC qua các ví dụ, NXB
Lao động – Xã Hội.
[3] Gerard Beekmans, Linux From Scratch V6.1.1, Gerard Beekmans.
[4] Xilinx, Xilinx University Program Virtex-II Pro Development System
Hardware Reference Manual UG069 (v1.0) March 8, 2005, Xilinx.
[5] Karim Yaghmour, Building Embedded Linux Systems, O'Reilly, April 2003
[6] Daniel P. Bovet, Marco Cesati, Understanding The Linux Kernel, O'Reilly,
October 2000
Website tham khảo
[1]
[2]
[3]
[4]
[5]
[6]
hulman.edu/~doering/PLD_Oasis/files/video_tutorials/XUPV2P
[7]
[8]
[9]
[10]
[11]
HOWTO.html
[12]
[13]
[14]
SVTH: Trần Quang Thuận – Phan Bá Minh. - 120 -
Nghiên cứu Linux trên hệ thống nhúng và ứng dụng.
Phụ lục: Source chương trình chạy trên Linux
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define type_file "rb"
#define byte_per_send 1000 // so byte moi lan truyen tu buffer di
#define byte_per_readfile 5000 // moi lan doc 100 byte vao buffer,sau do moi lan
truyen 100 byte trong buffer di
#define time 1
FILE *Xfile_stream;//tro vao thu muc /var/file.MP3
int main(int argc,char *argv[])
{
//**************Tao socket,chuan bi ket noi voi client ************************
printf("************ CHUONG TRINH FILE SERVER MP3 ***************\n");
int server_sockfd,client_sockfd;
int server_len,client_len;
struct sockaddr_in server_address;
struct sockaddr_in client_address;
server_sockfd=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
server_address.sin_family=AF_INET;
server_address.sin_addr.s_addr=htonl(INADDR_ANY);
server_address.sin_port=htons(7777);
server_len=sizeof(server_address);
bind(server_sockfd,(struct sockaddr *)&server_address,server_len);
listen(server_sockfd,5);
//******Kiem tra user name********************************************
char exitmain[10]="y";
while (!(exitmain[0]=='n')||(!exitmain[0]=='N'))
{
SVTH: Trần Quang Thuận – Phan Bá Minh. - 121 -
Nghiên cứu Linux trên hệ thống nhúng và ứng dụng.
char kiemtra[1];
client_sockfd=accept(server_sockfd,(struct sockaddr *)&client_address,
&client_len);
recv(client_sockfd,kiemtra,1,0);
close(client_sockfd);
system("clear");
if (kiemtra[0]=='a')
{
printf(" -------------------------------------------\n");
printf(" - Welcome Administrator -\n");
printf(" - Ban duoc quyen Download va Upload file -\n");
printf(" -------------------------------------------\n\n");
}
if (kiemtra[0]=='g')
{
printf(" -------------------------------------------\n");
printf(" - Welcome Visitor -\n");
printf(" - Ban duoc quyen Download file -\n");
printf(" -------------------------------------------\n\n");
}
char exit[10]="y";
while(!(exit[0]=='n')||(!exit[0]=='N'))
{
void delay(); //ham delay ,lam tre 1 khoang thoi gian
int get_lenght(char *file_name);//nhan ten cua file va tra lai do dai file
char file_lenght_buffer[10]; //buffer chua chieu dai cua file dang ky tu
char quit[10]="y"; //Bien quit de ket thuc hoac tiep tuc chuong trinh
int i,j,k,l,m,n;
//********Bat dau chuong trinh chinh************
printf(" *****************************************\n");
printf(" ******** START MAIN PROGRAM *************\n");
printf(" *****************************************\n");
///**************Lua chon che do download hoac upload
char select[1];//Bien select de chon U=Upload hoac D=Download
int Xflag;
SVTH: Trần Quang Thuận – Phan Bá Minh. - 122 -
Nghiên cứu Linux trên hệ thống nhúng và ứng dụng.
client_sockfd=accept(server_sockfd,(struct sockaddr
*)&client_address,&client_len);
printf("Server chap nhan ket noi");
recv(client_sockfd,select,1,0);
printf("\n");
close(client_sockfd);
if (select[m]=='d')
{
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ DOWNLOAD PROGRAMING $$$$$$$$$$$$$$$$$$$$$
printf("\n THUC HIEN CHE DO DOWNLOAD \n");
sleep(2);
//*********Search tat ca cac file mp3 co trong thu muc mp3_files,tra lai mang le
ten cac file
char name[200]="#"; //mang nay chua ten cac file seach duoc
char name_del[200]="#";
char dir_path[200]="/var/mp3/"; //ten thu muc can seach file thu muc tim
kiem,mac dinh la thu muc goc CF,sau khi mount se la thu muc /var
DIR *dir; //con tro thu muc
struct dirent *entry;
dir=opendir(dir_path);
if(dir==NULL) printf("open dir error"); else printf("\n dir= %d\n",dir);
int flag=1,file_name_lenght,file_list_lenght;
int number_of_file=0; //so file tim duoc trong thu muc
char end_of_file='#'; //danh dau giua ten cac file de phan biet duoc
//cac file
char end_of_string_name='@';//danh dau ket thuc phan ten cac file,de client
//biet duoc khi nao thi khong doc nua
char folder_1[2]=".",folder_2[3]=".."; //de biet khong dua thu muc goc vao
//danh sach file_list
while(flag) //bien flag se tra ve gia tri 0 khi ham doc
//file trong thu muc khong con tim thay file nao nua, dieu nay se tranh lam cho
//chuong trinh bi loi tran bo nho
{
entry=readdir(dir);
if(entry>0) flag=1; else flag=0;
printf("\nFlag = %d ",flag); //flag la co cho biet viec doc ten file
//co thanh cong hay khong,neu sau khi doc xong thi khong doc nua,vi doc nhieu se
//lam tran bo nho
if(flag==0) printf(" \n\n\n Da doc xong ten file ,khong doc nua \n");
SVTH: Trần Quang Thuận – Phan Bá Minh. - 123 -
Nghiên cứu Linux trên hệ thống nhúng và ứng dụng.
else
{
file_name_lenght=strlen((entry)->d_name);
if((!strcmp(folder_1,(entry-
>d_name)))||(!strcmp(folder_2,(entry->d_name)))) printf("foleder");
else
{
number_of_file= number_of_file+1;
strcat(name,(entry)->d_name);
strcat(name,"#");
printf(" %40s",(entry)->d_name);
printf(" FILE LENGHT= %d ",file_name_lenght);
}
}
}
strcat(name,"@");
file_list_lenght=strlen(name);
while(file_list_lenght<100)
{
strcat(name,"@");
file_list_lenght=strlen(name);
}
printf("\n %s %d \n lengh= %d", name, number_of_file,
file_list_lenght);
//******************Bat dau vong lap cho server,se mo socket va cho client ket noi
while(!(quit[0]=='n')||(!quit[0]=='N')) //lam cho den khi ngoi su dung yeu
//cau ket thuc server
{
char ch;
printf("Server waiting\n");
client_sockfd=accept(server_sockfd,(struct sockaddr *)&client_address,
&client_len);
printf("Chuan bi nhan message\n"); //luc nay server dang cho de nhan
//mot Message tu client ,o day la ten file can download ve client
char file_name_array[50]="/var/mp3/";//them vao client de ghep vao
//ten,muc dich la tro den dung file
char file_name_temp[50];
SVTH: Trần Quang Thuận – Phan Bá Minh. - 124 -
Nghiên cứu Linux trên hệ thống nhúng và ứng dụng.
recv(client_sockfd,file_name_temp,50,0); //nhan message tu client va
//dua vao buffer file_name_temp;
if(!(*(file_name_temp)=='#'))
strcat(file_name_array,file_name_temp); //neu client gui chuoi co dau
//# o dau thi theo quy dinh cua chuong trinh se gui cho client list cac file trong
//thu muc
if(*(file_name_temp)=='#') //luc nay dau chuoi la #,nen server se gui
//file-list cho client
{
send(client_sockfd,name,200,0);
printf("\nTruyen xong file name list \n");
strcpy(name,name_del);
close(client_sockfd);
client_sockfd=accept(server_sockfd,(struct sockaddr
*)&client_address,&client_len);
recv(client_sockfd,file_name_temp,50,0);
strcat(file_name_array,file_name_temp);
}
//****************Server nhan duoc ten file ma client yeu cau se bat dau qua trinh
truyen file cho client
printf("\nNhan xong\nClient yeu cau truyen file : %s\n",
file_name_array);
sleep(1);
for(i=0;i<50;i++)
{
printf("%c",*(file_name_array+i));
}
printf("\n");
//***********tinh chieu dai cua file ma client yeu cau*******************
int file_lenght;
char *file_name; //con tro file_name tro den mang chua ten cua file
//ma client yeu cau
file_name=&file_name_array[0];
printf("\nGeting the lenght of file : %s",file_name_array);//in ra ten
//cua file ma client yeu cau
file_lenght=get_lenght(file_name_array); //Dung ham get_lenght de lay
//chieu dai file,tra ve chieu dai cua file
int file_lenght_temp;
file_lenght_temp=file_lenght;
SVTH: Trần Quang Thuận – Phan Bá Minh. - 125 -
Nghiên cứu Linux trên hệ thống nhúng và ứng dụng.
printf("\nLenght of file= %ld",file_lenght);
//Quy doi chieu dai byte dang so nguyen ra chuoi ky tu de truyen len client biet ma
//chuan bi nhan bao nhieu byte
for(i=9;i>=0;i--)
{
file_lenght_buffer[i]=file_lenght_temp%10+'0';
file_lenght_temp=file_lenght_temp/10;
printf("\n file_lenght_buffer_temp=%ld ",file_lenght_temp);
printf("%c",file_lenght_buffer[i]);
}
send(client_sockfd,file_lenght_buffer,10,0);
printf("\n truyen file lenght xong ,file_lenght= %d \n",file_lenght);
int number_times_readfile; //So lan can phai doc file vao buffer de chuan
//bi truyen cho client, Theo khai bao tren se doc 2000 byte tu file vao buffer
int remain_in_file ; //do cac file khong chan,nen lan doc file cuoi
cung se khong du 2000, remain_in_file se la so byte can doc lan cuoi
file_lenght_temp=file_lenght;
printf("file_lenght_temp = %d",file_lenght_temp);
number_times_readfile=file_lenght_temp/byte_per_readfile; //tinh toan
number_times_readfile, va remain_in_file
remain_in_file=file_lenght_temp-number_times_readfile*byte_per_readfile;
printf("So lan doc file = %d so byte can doc lan cuoi = %d
",number_times_readfile,remain_in_file); //dong bebug
char file_data_buffer[byte_per_readfile]; //buffer chua data doc len tu file
char file_data_send_buffer[byte_per_send]; //buffer chua data file truoc khi
truyen
//*********Doc file va truyen file cho client *********************************
int count;//bien dung de tinh so lan can fai doc file_data_buffer vao
file_data_send_buffer
int temp; //bien tam
char *buffer_ptr; //con tro tro vo buffer file_data_buffer de chi ra cho bat
dau send file
char r_error[1];//trong qua trinh doc client se gui ve server mot ky tu de
thong bao la no co doc du khong neu ki tu nay la w (wrong) thi server se gui lai va
client cung se nhan lai lan do int percent % file send duoc
count=byte_per_readfile/byte_per_send;
FILE *file_stream_s; //mo file,chuan bi doc file
file_stream_s=fopen(file_name,type_file);
printf("\n *******************************************");
SVTH: Trần Quang Thuận – Phan Bá Minh. - 126 -
Nghiên cứu Linux trên hệ thống nhúng và ứng dụng.
for(i=0;i<number_times_readfile;i++)
{
fread(file_data_buffer,1,byte_per_readfile,file_stream_s); //doc data
tu file vao file_data_buffer
//percent=i*byte_per_readfile*100/file_lenght;
//printf("\n Da send xong %d phan tram
i= %d ...completed", percent,i);
for(j=0;j<count;j++)
{
buffer_ptr=&file_data_buffer[j*byte_per_send];
send(client_sockfd,buffer_ptr,byte_per_send,0);
recv(client_sockfd,r_error,1,0);
while (r_error[0]=='w')
{
send(client_sockfd,buffer_ptr,byte_per_send,0);
recv(client_sockfd,r_error,1,0);
}
}
}
//*******************Doc so file con du trong file **************************
//printf("\nDoc file lan cuoi ");
fread(file_data_buffer,1,remain_in_file,file_stream_s);//doc data tu file
vao file_data_buffer
count=remain_in_file/byte_per_send;
temp=remain_in_file-count*byte_per_send;
for(j=0;j<count;j++)
{
buffer_ptr=&file_data_buffer[j*byte_per_send];
send(client_sockfd,buffer_ptr,byte_per_send,0);
recv(client_sockfd,r_error,1,0);
while (r_error[0]=='w')
{
send(client_sockfd,buffer_ptr,byte_per_send,0);
recv(client_sockfd,r_error,1,0);
}
}
SVTH: Trần Quang Thuận – Phan Bá Minh. - 127 -
Nghiên cứu Linux trên hệ thống nhúng và ứng dụng.
//*******************doc so du trong so du trong lai cua lan truyen cuoi cung
fclose(file_stream_s); //dong file
printf("\nDa Send xong file\n");
printf("Tiep Tuc Download:(y/n) : ");
close(client_sockfd); //dong socket
client_sockfd=accept(server_sockfd,(struct sockaddr *)&client_address,
&client_len);
recv(client_sockfd,quit,1,0);
printf("%c\n",quit[0]);
close(client_sockfd);
}//end of while add
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$ end of download $$$$$$$$$$$$$$$$$$$$$$
}
if (select[m]=='u')
{
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$ UPLOAD PROGRAMING $$$$$$$$$$$$$$$$$$$$
printf("\n THUC HIEN CHE DO UPLOAD:\n");
sleep(2);
while(!(quit[0]=='n')||(!quit[0]=='N')) //lam cho den khi ngoi su dung yeu
cau ket thuc server {
//***************Lay ten cua cac file ben client**********************
char Xbuffer_file_name[100];//ten cua cac file upload
char Xbuffer_file_lenght[10];//buffer chua chieu dai file dang char
long int Xfile_lenght;//chieu dai file dang interger
int a,b,c,d;
printf("Server waiting\n");
client_sockfd=accept(server_sockfd,(struct sockaddr *)&client_address,
&client_len);
printf("Connect TRUE\n");
recv(client_sockfd,Xbuffer_file_name,100,0);//Nhan ten file tu client,va dua
thu do dai luon
printf("Ten nhan duoc: %s\n",Xbuffer_file_name);
printf("So ky tu ban dau trong chuoi: %d\n",strlen(Xbuffer_file_name));
recv(client_sockfd,Xbuffer_file_lenght,10,0);//Nhan chieu dai file dang char
//************Chuyen doi file_lenght dang char sang dang interger****
Xfile_lenght=0;
for (a=0;a<10;a++)
SVTH: Trần Quang Thuận – Phan Bá Minh. - 128 -
Nghiên cứu Linux trên hệ thống nhúng và ứng dụng.
Xfile_lenght=Xfile_lenght*10+(Xbuffer_file_lenght[a]-'0');
printf("Chieu dai cua file la: %ld byte\n",Xfile_lenght);
//************Nhan Data tu client***********************************
char Xfile_name_array[100]="/var/mp3/";//mang chua ten file
strcat(Xfile_name_array,Xbuffer_file_name);
printf("Chep duong dan path: %s\n",Xfile_name_array);
Xfile_stream=fopen(Xfile_name_array,"wb");
int Xcount,Xtemp;//dem so lan can phai nhan du du lieu
int Xcount_s,Xtemp_s;
int per_read=5000;
int per_recv=1000;
char Xfile_buffer[per_recv];
//int Xpercent;
int dem;
dem=per_read/per_recv;
count=Xfile_lenght/per_read;
Xtemp=Xfile_lenght-Xcount*per_read;
Xcount_s=Xtemp/per_recv;
Xtemp_s=Xtemp-Xcount_s*per_recv;
printf("So lan truyen 5000 byte: %d\n",Xcount);
printf("So lan truyen du byte: %d\n",Xtemp);
printf("************************************************\n");
sleep(1);
// nhan phan nguyen X
if (Xcount>0)
for(b=0;b<Xcount;b++)
{
for (c=0;c<dem;c++)
{
a=recv(client_sockfd,Xfile_buffer,per_recv,0);
while (a != per_recv)
{
send(client_sockfd,"w",1,0);
a=recv(client_sockfd,Xfile_buffer,per_recv,0);
}
send(client_sockfd,"o",1,0);
SVTH: Trần Quang Thuận – Phan Bá Minh. - 129 -
Nghiên cứu Linux trên hệ thống nhúng và ứng dụng.
fwrite(Xfile_buffer,1,per_recv,Xfile_stream);
}
}
// nhan phan du Y
for (d=0;d<Xcount_s;d++)
{
a=recv(client_sockfd,Xfile_buffer,per_recv,0);
while (a != per_recv)
{
send(client_sockfd,"w",1,0);
a=recv(client_sockfd,Xfile_buffer,per_recv,0);
}
send(client_sockfd,"o",1,0);
fwrite(Xfile_buffer,1,per_recv,Xfile_stream);
}
recv(client_sockfd,Xfile_buffer,Xtemp_s,0);
fwrite(Xfile_buffer,1,Xtemp_s,Xfile_stream);
fclose(Xfile_stream);
printf("\nDa nhan xong file\n");
recv(client_sockfd,quit,1,0);
printf("Continue Upload ? (y/n) : %c\n",quit[0]);
close(client_sockfd);
}//end of while
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$ end of upload $$$$$$$$$$$$$$$$$$$$$$$$$
}//end of if (select[0]=='u')
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$ Reboot Kit XUP $$$$$$$$$$$$$$$$$$$$$$$$$
if (select[m]=='r')
{
printf("****************WAITING REBOOT SYSTEM*****************\n");
printf("*******Reboot Kit XUP Virtex-II Pro Development*******");
system("reboot");
}//end of if (select[0]=='r')
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$ Power off upload $$$$$$$$$$$$$$$$$$$$$$$$$
if (select[m]=='p')
{
printf("****************WAITING SHUTDOWN SYSTEM****************\n");
SVTH: Trần Quang Thuận – Phan Bá Minh. - 130 -
Nghiên cứu Linux trên hệ thống nhúng và ứng dụng.
printf("*******Shutdown Kit XUP Virtex-II Pro Development******");
system("poweroff");
}//end of if (select[0]=='p')
printf("\n************************************************\n");
printf("\nCONTINUE MAIN PROGRAM ? (y/n) :");
client_sockfd=accept(server_sockfd,(struct sockaddr *)&client_address,
&client_len);
recv(client_sockfd,exit,1,0);
printf("%c\n",exit[0]);
close(client_sockfd);
if((exit[0]=='n')||(exit[0]=='N')) {
printf(" \nKET THUC CHUONG TRINH CHINH\n");
printf("\n************************************************\n");
}
else printf("\nDang cho ket noi\n");
}//end of while exit[]
//-------------------------------------------------------------------
client_sockfd=accept(server_sockfd,(struct sockaddr *)&client_address,
&client_len);
recv(client_sockfd,exitmain,1,0);
close(client_sockfd);
if((exitmain[0]=='n')||(exitmain[0]=='N'))
printf(" \nEXIT\n");
else
{
system("clear");
printf("LOGIN:\n");
}
}//end of while exitmain[]
//---------------------------------------------------------------------
} //end of main
//.......................................................................
int get_lenght(char *file_name)
{
int file_lenght,file_start,file_end;
int i=0;
SVTH: Trần Quang Thuận – Phan Bá Minh. - 131 -
Nghiên cứu Linux trên hệ thống nhúng và ứng dụng.
FILE *file_stream;
file_stream=fopen(file_name,type_file);
if(!file_stream)
{
printf("\nKhong the mo dc file");
}
else
{
file_start=ftell(file_stream);
fseek(file_stream,0,2);//di chuyen con tro toi moc (#)*****(@)
file_end=ftell(file_stream);
file_lenght=file_end-file_start;
printf("\n File lenght = %d ",file_lenght);
}
return file_lenght;
}
//...............................................................................
void delay()
{
int i,j,k,s;
for(i=0;i<time;i++)
for(j=0;j<10;j++)
for(k=0;k<1000;k++)
if(s>100) s=0; else
s=s+1;
}
SVTH: Trần Quang Thuận – Phan Bá Minh. - 132 -
Nghiên cứu Linux trên hệ thống nhúng và ứng dụng.
Phụ lục: Source code của chương trình MFC
Download module:
SOCKET lhSocket;
SOCKADDR_IN lSockAddr;
WSADATA wsaData;
int lConnect;
int lLength;
char ip_add;
char lData[]="HELLO";
if(WSAStartup(MAKEWORD(2,2),&wsaData) != 0)
{
cout<<"Socket Initialization Error. Program aborted\n";
return;
}
lhSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(lhSocket == INVALID_SOCKET)
{
cout<<"Invalid Socket "<<GetLastError()<<". Program Aborted\n"<<endl;
}
memset(&lSockAddr,0, sizeof(lSockAddr));
lSockAddr.sin_family = AF_INET;
lSockAddr.sin_port = ntohs(m_port);
lSockAddr.sin_addr.s_addr = inet_addr(m_ip_address_msg);
lConnect = connect(lhSocket,(SOCKADDR *)&lSockAddr,sizeof(SOCKADDR_IN));
if(lConnect != 0)
{
MessageBox("Connect Fail");
return;
}
//.............tao file...................................................
FILE *file_stream;
int last_lenght;
int i,j,k;
char file_lenght_buf[20];
SVTH: Trần Quang Thuận – Phan Bá Minh. - 133 -
Nghiên cứu Linux trên hệ thống nhúng và ứng dụng.
long int file_lenght=0;
//..........can cu vao stt tren edit box cua spin ma gan ten bai hat vao chuoi de
down ve
send(lhSocket,m_msg,50,0);//strlen(m_msg)
//............................... getlenght of file
recv(lhSocket,file_lenght_buf,10,0);
for(i=0;i<10;i++)
file_lenght=file_lenght*10+(file_lenght_buf[i]-'0');
UpdateData(FALSE);
// doan chuong trinh lay data tu server
int count,temp;//dem so lan can phai nhan du lieu
int count_s,temp_s;
int dem;
int per_read=5000;
int per_recv=1000;
dem=per_read/per_recv;
count=file_lenght/per_read;//moi lan nhan 100 byte vao buffer
temp=file_lenght-per_read*count;
count_s=temp/per_recv;
temp_s=temp-count_s*per_recv;
file_name_play_list[number_of_file_in_playlist]=path_save;
file_name_play_list[number_of_file_in_playlist]
="d:\\playlist\\"+m_msg;
long int recv_byte=0;
int g;
file_stream=
fopen(file_name_play_list[number_of_file_in_playlist],"wb");
current_file=path_save;
char file_buffer[1000];
if(count>0)
for(i=0;i<count;i++)
{
for(j=0;j<dem;j++)
{
g=recv(lhSocket,file_buffer,per_recv,0);
while (g != per_recv)
SVTH: Trần Quang Thuận – Phan Bá Minh. - 134 -
Nghiên cứu Linux trên hệ thống nhúng và ứng dụng.
{
send(lhSocket,"w",1,0);
printf("NOP\n");
g=recv(lhSocket,file_buffer,per_recv,0);
}
send(lhSocket,"o",1,0);
fwrite(file_buffer,1,per_recv,file_stream);
recv_byte=recv_byte+g;
}
percent=(int) recv_byte*100/file_lenght;
m_run.SetPos(percent);
UpdateData(FALSE);
}
for (j=0;j<count_s;j++)
{
g=recv(lhSocket,file_buffer,per_recv,0);
while (g != per_recv)
{
send(lhSocket,"w",1,0);
printf("NOP\n");
g=recv(lhSocket,file_buffer,per_recv,0);
}
send(lhSocket,"o",1,0);
fwrite(file_buffer,1,per_recv,file_stream);
recv_byte=recv_byte+g;
percent=(int) recv_byte*100/file_lenght;
m_run.SetPos(percent);
UpdateData(FALSE);
}
g=recv(lhSocket,file_buffer,temp_s,0);
fwrite(file_buffer,1,temp_s,file_stream);
fclose(file_stream);
closesocket(lhSocket);
SVTH: Trần Quang Thuận – Phan Bá Minh. - 135 -
Nghiên cứu Linux trên hệ thống nhúng và ứng dụng.
Upload Module:
SOCKET lhSocket;
SOCKADDR_IN lSockAddr;
WSADATA wsaData;
int lConnect;
int lLength;
char ip_add;
char lData[]="HELLO";
if(WSAStartup(MAKEWORD(2,2),&wsaData) != 0)
{
cout<<"Socket Initialization Error. Program aborted\n";
return;
}
lhSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(lhSocket == INVALID_SOCKET)
{
cout<<"Invalid Socket "<<GetLastError()<<". Program Aborted\n"<<endl;
}
memset(&lSockAddr,0, sizeof(lSockAddr));
lSockAddr.sin_family = AF_INET;
lSockAddr.sin_port = ntohs(m_port);
lSockAddr.sin_addr.s_addr = inet_addr(m_ip_address_msg);
lConnect = connect(lhSocket,(SOCKADDR *)&lSockAddr,sizeof(SOCKADDR_IN));
if(lConnect != 0)
{
MessageBox("Connect Fail");
return;
}
else
send(lhSocket,Xfile_name_send,100,0);
#define byte_per_read 5000
#define byte_per_send 1000
int number_time_read_file; //so lan read data vao buffer ,moi lan
truyen 5000
int remain_in_file;//data du remain_in_file= Y
number_time_read_file=Xfile_lenght_s/byte_per_read;
SVTH: Trần Quang Thuận – Phan Bá Minh. - 136 -
Nghiên cứu Linux trên hệ thống nhúng và ứng dụng.
remain_in_file=Xfile_lenght_s-number_time_read_file*byte_per_read;
//mo file.MP3
FILE *f_stream_s;
f_stream_s=fopen(Xfile_name_buffer,"rb");
char r_error[1];
char file_data_buffer[byte_per_read];
char file_data_send_buffer[byte_per_send];
char *buffer_ptr;//con tro tro vao file_data_buffer
Xcount= byte_per_read/byte_per_send;
int Xg;
int Xrecv_byte_s;
//Giai quyet phan chan nguyen cua Data =X
//doc 5000 byte tu file
for (b=0;b<number_time_read_file;b++)
{
fread(file_data_buffer,1,byte_per_read,f_stream_s);
//truyen 200 byte
for (c=0;c<Xcount;c++)
{
buffer_ptr=&file_data_buffer[c*byte_per_send];//read 200
byte =>buffer_ptr
Xg=send(lhSocket,buffer_ptr,byte_per_send,0);//gui 200
byte cho server
printf("NOP");
recv(lhSocket,r_error,1,0);
while (r_error[0] == 'w')
{
send(lhSocket,buffer_ptr,byte_per_send,0);//neu sai gui
lai
Xg=recv(lhSocket,r_error,1,0);//nhan ve gia tri
correct/false
}
Xrecv_byte_s=Xrecv_byte_s+Xg;
}
Xpercent=(int) Xrecv_byte_s*100/Xfile_lenght_s;
m_run.SetPos(Xpercent);
SVTH: Trần Quang Thuận – Phan Bá Minh. - 137 -
Nghiên cứu Linux trên hệ thống nhúng và ứng dụng.
UpdateData(FALSE);
}
//Giai quyet phan du le <5000 cua Data =Y
fread(file_data_buffer,1,remain_in_file,f_stream_s);
Xcount=remain_in_file/byte_per_send;
Xtemp=remain_in_file-Xcount*byte_per_send;
for(d=0;d<Xcount;d++)
{
buffer_ptr=&file_data_buffer[d*byte_per_send];
Xg=send(lhSocket,buffer_ptr,byte_per_send,0);
recv(lhSocket,r_error,1,0);
while (r_error[0] == 'w')
{
send(lhSocket,buffer_ptr,byte_per_send,0);//neu sai gui
lai
Xg=recv(lhSocket,r_error,1,0);//nhan ve gia tri
correct/false
}
Xrecv_byte_s=Xrecv_byte_s+Xg;
Xpercent=(int) Xrecv_byte_s*100/Xfile_lenght_s;
m_run.SetPos(Xpercent);
UpdateData(FALSE);
}
//Giai quyet phan du cuoi cung <200
fread(file_data_buffer,1,Xtemp,f_stream_s);
send(lhSocket,buffer_ptr,Xtemp,0);
fclose(f_stream_s);
closesocket(lhSocket);
}
SVTH: Trần Quang Thuận – Phan Bá Minh. - 138 -
Các file đính kèm theo tài liệu này:
- Nghiên cứu linux trên hệ thống nhúng và ứng dụng.pdf