Đề tài Nghiên cứu linux trên hệ thống nhúng và ứng dụng

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

pdf138 trang | Chia sẻ: lvcdongnoi | Lượt xem: 4182 | Lượt tải: 1download
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:

  • pdfNghiên cứu linux trên hệ thống nhúng và ứng dụng.pdf