Successfully reported this slideshow.

Linux+03

3,216 views

Published on

Bai giang Linux (Phan3)

  • Be the first to comment

Linux+03

  1. 1. .: CÔNG NGHỆ LINUX :. Môn học: KHÓA 3 CHƯƠNG TRÌNH ĐÀO TẠO THẠC SĨ CNTT QUA MẠNG ĐẠI HỌC QUỐC GIA TP. HỒ CHÍ MINH TRƯỜNG ĐẠI HỌC CÔNG NGHỆ THÔNG TIN Giảng viên: TS. Tô Tuấn (Viện CNTT, BQP) Email: totuan4@yahoo.com Trợ lý kỹ thuật: Nguyễn Vạn Phúc, Vũ Mạnh Cường
  2. 2. Chương 4: Nhập môn lập trình Linux <ul><li>Bao gồm các phần sau: </li></ul><ul><ul><li>Linux và Unix </li></ul></ul><ul><ul><li>Cộng đồng GNU và General Public License </li></ul></ul><ul><ul><li>Lập trình trên Linux </li></ul></ul><ul><ul><li>Chương trình Unix và Linux </li></ul></ul><ul><ul><li>Chương trình Linux đầu tay helloworld.c </li></ul></ul><ul><ul><li>Tìm trợ giúp về trình biên dịch </li></ul></ul><ul><ul><li>Phát triển chương trình với ngôn ngữ C </li></ul></ul><ul><ul><li>Thư viện liên kết trên Linux </li></ul></ul>CITD - VNUHCM
  3. 3. <ul><li>4.1. Linux và Unix </li></ul><ul><li>Unix được đánh giá là một HĐH mạnh, ổn định. Trước đây được xem là một HĐH mã nguồn mở và từ khi Sun Microsystems nâng cấp lên thành một sản phẩm thương mại  mất dần tính mở của HĐH Unix. </li></ul><ul><li>Các dòng sản phẩm Server của Microsoft đã và đang cạnh tranh với các dòng tương đương thuộc họ UNIX (như FreeBSD, Linux, Debian, SCO Unix,…) </li></ul><ul><li>Theo dòng lịch sử thì với việc kế thừa và phát huy những tính năng nổi bật của một HĐH đã qua thử thách - UNIX – { mã nguồn mở + tính ổn định }  Linux đã được ủng hộ và được sử dụng bởi cộng đồng trên toàn thế giới </li></ul>
  4. 4. <ul><li>Một số tính năng khác của HĐH Linux so với HĐH Unix : </li></ul><ul><ul><li>Là hạt nhân cung cấp các chức năng cần thiết tối thiểu của HĐH tựa Unix ( Linux giống Unix gần 98% ) </li></ul></ul><ul><ul><li>Là một sản phẩm có giá trị do Unix không có phiên bản chạy trên hệ máy PC với kiến trúc Intel </li></ul></ul>
  5. 5. <ul><ul><li>Chương trình viết trên Unix đều có thể chạy tốt trên Linux và ngược lại </li></ul></ul><ul><ul><li>Linux đã được phát triển dựa trên việc tận dụng những ưu điểm và khắc phục những khuyết điểm của các HĐH tựa UNIX </li></ul></ul><ul><ul><li>Linux ngày nay được sử dụng rộng rãi và chính do yếu tố phổ biến trên đã được sự hỗ trợ giúp đỡ của khá nhiều cộng đồng người dùng trên thế giới </li></ul></ul>
  6. 6. <ul><li>4.2. Cộng đồng GNU và General Public License </li></ul><ul><li>Ngoài HĐH, còn có các chương trình ứng dụng phục vụ cho yêu cầu của người dùng </li></ul><ul><li>Cộng đồng Open Source đã xây dựng nhiều ứng dụng có khả năng chạy được trên Unix/Linux và nhìn chung theo xu hướng hiện đại nhằm lôi kéo người dùng Linux theo phương châm “Windows có gì ~ Linux có tương ứng như vậy” </li></ul>
  7. 7. <ul><li>- GNU – { G NU’s N ot U NIX } – GNU theo nguyên gốc tiếng Anh là “linh dương đầu bò” <=> là biểu tượng của tổ chức cộng đồng mã nguồn mở </li></ul><ul><li>Tham khảo các phần mềm ứng dụng miễn phí tại địa chỉ http:// www.gnu.org/software/software.html </li></ul><ul><li>Khi sử dụng các phần mềm của tổ chức GNU thì cần phải tuân thủ một số quy định của tổ chức trên  Giấy phép chứng nhận GPL còn gọi là copyleft thay cho copyright cho các chứng nhận bản quyền thương mại </li></ul>
  8. 8. <ul><li>Một số bộ công cụ biên dịch C/C++: </li></ul>Ý nghĩa Trình biên dịch Bộ phân tích tương thích yacc của UNIX Bison Hệ vỏ Shell hỗ trợ cơ chế dòng lệnh bash Trình soạn thảo văn bản GNU Emacs Trình quản lý mã nguồn và quản lý thư viện GNU make Trình gỡ lỗi gdb Trình biên dịch C++ g++ Trình biên dịch C gcc
  9. 9. <ul><li>4.3. Lập trình trên Linux </li></ul><ul><li>Nguyên thủy Unix được viết bằng C và phần lớn các ứng dụng trên Unix được viết bằng C </li></ul><ul><li>Ngoài C là lựa chọn duy nhất, có thể sử dụng Pascal, Assembly hoặc Perl để xây dựng các chương trình cho Linux </li></ul>UNIX Bourne Shell Tcl / Tk SQL Smalltalk Scheme Python Prolog PostScript Perl Pascal Objective C Oberon Modula 3 Modula 2 Lisp JavaScript Java Icon Fortran Forth Eiffel C++ C Ada
  10. 10. <ul><li>4.4. Chương trình Unix và Linux </li></ul><ul><li>Chương trình trên Unix và Linux tồn tại ở hai dạng: </li></ul><ul><ul><li>Dạng thực thi (tập tin nhị phân) </li></ul></ul><ul><ul><li>Dạng thông dịch (tập tin script) </li></ul></ul><ul><li> File chương trình thực thi ~ như tập tin .exe của MS-DOS/Windows </li></ul><ul><li> File script là những chỉ thị lệnh được thực thi bởi shell hay trình thông dịch nào đó (Perl, Python, Tcl, ...)  tương tự như các tập tin .bat của MS-DOS, VBScript và JavaScript của Windows Script Host </li></ul><ul><li>- Các file script và chương trình nhị phân đều có khả năng và mạnh ngang nhau  Do vậy, lúc thực thi khó phân biệt được đâu là lệnh gọi chương trình nhị phân và đâu là lệnh thực hiện script </li></ul><ul><li>- Khi chương trình được gọi, Linux sẽ tìm đường dẫn đến nơi chứa tập tin chương trình trong biến môi trường PATH . Thông thường, biến này chứa các đường dẫn sau /bin , /user/bin , /usr/local/bin </li></ul>
  11. 11. - Đối với người quản trị hệ thống, có thêm một số đường dẫn trỏ đến thư mục /sbin , /usr/sbin - Unix/Linux sử dụng dấu “ : ” để phân cách các đường dẫn trong biến môi trường PATH , trong khi MS-DOS dùng dấu “ ; ” - Ví dụ: PATH = /bin: /user/bin: /usr/local/bin:.:
  12. 12. <ul><li>4.5. Chương trình Linux đầu tay ( Helloworld.c ) </li></ul><ul><li>Dùng trình soạn thảo bất kỳ (trong Console Mode) để soạn thảo source code như: </li></ul><ul><ul><li> vi </li></ul></ul><ul><ul><li> cat </li></ul></ul><ul><ul><li> Dùng chức năng Edit trong mc (Midnight Commander) </li></ul></ul><ul><ul><li> v.v... </li></ul></ul><ul><li>- Cách sử dụng: </li></ul><ul><ul><li> vi helloworld.c </li></ul></ul><ul><ul><li> cat > helloworld.c </li></ul></ul><ul><li>- Một giao diện khác tương tự như trong Turbo C của Borland thì sử dụng trình soạn thảo wpe (cho phép kết hợp chức năng biên dịch của cc, gcc, pascal ) </li></ul><ul><li>- Tham khảo Ví dụ 4-1 : helloworld.c </li></ul>
  13. 13. Windows Programming Environment (WPE) ==  -----  -----  == Hình 4.1 Trình wpe trong chế độ Console
  14. 14. Windows Programming Environment (WPE) ==  -----  -----  == Hình 4.2 Trình wpe trong chế độ X-Windows
  15. 15. - Sử dụng gcc (hoặc cc ) để biên dịch như sau: # gcc helloworld.c -o helloworld # ./helloworld Hello World #
  16. 16. <ul><li>4.6. Tìm trợ giúp về trình biên dịch </li></ul><ul><li>Trong trình gcc có rất ít tùy chọn (-o, -g, -l, -I, v.v...). </li></ul><ul><li>Sử dụng lệnh man để tham khảo thêm một số tuỳ chọn khác. </li></ul><ul><li>Trong bộ chương trình GNU cũng kèm theo chương trình info có ưu điểm là hướng dẫn sử dụng phần mềm rất chi tiết. Cách thức dùng lệnh info như man. </li></ul>
  17. 17. <ul><li>4.7. Phát triển chương trình với ngôn ngữ C </li></ul><ul><li>Sử dụng ngôn ngữ C làm ngôn ngữ chính trong chương trình </li></ul><ul><li>Ngôn ngữ lập trình C không phụ thuộc vào HĐH nào </li></ul><ul><li>4.7.1. Chương trình trên Linux </li></ul><ul><li>Cần nắm rõ vị trí đặt tài nguyên để xây dựng chương trình như trình biên dịch, file thư viện, các file header khai báo hàm và cấu trúc dữ liệu, ... </li></ul><ul><li>Trình biên dịch gcc thường được đặt trong /usr/bin hoặc usr/local/bin . Khi biên dịch, gcc cần nhiều file hỗ trợ như các tập tin thư viện liên kết (trong /lib hoặc /usr/local/lib ), các file C header (trong /usr/include hoặc /usr/local/include ), v.v... </li></ul><ul><li>Chương trình sau khi biên dịch có thể đặt bất kỳ đâu trên hệ thống miễn là HĐH có thể tìm thấy trong biến môi trường PATH hoặc theo đường dẫn tuyệt đối trong dòng lệnh. </li></ul>
  18. 18. <ul><li>4.7.2. Các file header </li></ul><ul><li>File header trong C chứa định nghĩa các hàm, các hằng cùng với những cấu trúc dữ liệu cần cho quá trình biên dịch </li></ul><ul><li>Ví dụ một khai báo header trong C: </li></ul><ul><ul><li>#include <sys/types.h> </li></ul></ul><ul><li>- Trình biên dịch sẽ tìm file header có tên là types.h trong thư mục /usr/include/sys </li></ul><ul><li>- Đối với các hàm lập trình đồ hoạ X-Window, các file header nằm trong thư mục /usr/include/X11 </li></ul><ul><li>- Sử dụng tùy chọn -I để chỉ ra thư mục chứa các file header của riêng mình (khác với thư mục mặc định của hệ thống). </li></ul><ul><li>- Ví dụ: </li></ul><ul><ul><li># gcc –I /usr/mypro/include test.c -o test </li></ul></ul><ul><li>- Xem thông tin về các hàm trong thư viện # man <function name> </li></ul>
  19. 19. <ul><li>4.7.3. Các file thư viện </li></ul><ul><li>Để tạo ra chương trình thực thi, cần có các file thư viện </li></ul><ul><li>Trong Linux, các file thư viện thường là “ .a ” , “ .so ” , “. sa ” và được bắt đầu bằng tiếp đầu ngữ “ lib ”. Ví dụ: libutil.a hoặc libc.so  Đây là tên các thư viện trong Linux </li></ul><ul><li>- Có 2 loại thư viện liên kết: </li></ul><ul><li>• Liên kết động (Dynamic) </li></ul><ul><li>• Liên kết tĩnh (Static) </li></ul><ul><li>- Khi biên dịch, thông thường chương trình liên kết ( ld ) sẽ tìm thư viện trong 2 thư mục chuẩn /usr/lib và /lib </li></ul>
  20. 20. <ul><li>4.8. Thư viện liên kết trên Linux </li></ul><ul><li>Hình thức đơn giản nhất của thư viện là tập hợp các file đối tượng “ .o ” do trình biên dịch tạo ta ở bước biên dịch với tùy chọn -c </li></ul><ul><ul><li>#gcc -c helloworld.c </li></ul></ul><ul><li>- Lúc này trình biên dịch chưa tạo ra file thực thi mà tạo ra file đối tượng helloworld.o (file này chứa mã máy của chương trình đã được tổ chức lại ~ các file “ .o ” này tương tự như các file “ .obj ” do trình biên dịch C sinh ra trên DOS hoặc Windows) </li></ul><ul><li>- Để tạo ra file thực thi, thực hiện bước cuối cùng (gọi linker ld ) </li></ul><ul><ul><li># gcc helloworld.o -o helloworld </li></ul></ul><ul><li>- Nếu không dùng khoá chuyển “ -c ” thì trình biên dịch sẽ thực hiện cả hai bước trên đồng thời. </li></ul>
  21. 21. <ul><li>4.8.1. Thư viện liên kết tĩnh </li></ul><ul><li>Là các thư viện khi liên kết trình biên dịch sẽ lấy toàn bộ mã thực thi của hàm trong thư viện đưa vào chương trình chính. </li></ul><ul><li>Chương trình sử dụng thư viện liên kết tĩnh này chạy độc lập với thư viện sau khi biên dịch. </li></ul><ul><li>Do đó khi cần sửa chữa hoặc nâng cấp  Biên dịch lại </li></ul><ul><li>Tham khảo Ví dụ 4-2: fred.c </li></ul><ul><li>Tham khảo Ví dụ 4-3: bill.c </li></ul><ul><li>Tiến hành biên dịch để tạo ta 2 file đối tượng “ .o ” </li></ul><ul><ul><li>#gcc -c fred.c bill.c </li></ul></ul><ul><li>Tạo file tiêu đề để khai báo các hàm nguyên mẫu của người sử dụng </li></ul><ul><li>Tham khảo Ví dụ 4-4: lib.h </li></ul><ul><li>- Chương trình chính triệu gọi 2 hàm trên: Ví dụ 4-5: program.c </li></ul>
  22. 22. <ul><li>Sau khi biên dịch thành các tập tin .o, cần tạo tập tin thực thi như sau: </li></ul><ul><ul><li># gcc program.o bill.o fred.o –o program </li></ul></ul><ul><li>Cách tạo thư viện liên kết tĩnh: </li></ul><ul><ul><li># ar –cvr libfoo.a bill.o fred.o </li></ul></ul><ul><li>Biên dịch và hợp nhất với thư viện liên kết tĩnh: </li></ul><ul><ul><li># gcc program.c –o program –L. -lfoo </li></ul></ul>
  23. 23. <ul><li>4.8.2. Thư viện liên kết động </li></ul><ul><ul><ul><li>4.8.2.1. Tạo và sử dụng thư viện liên kết động .so </li></ul></ul></ul><ul><li>Thư viện liên kết tĩnh có nhược điểm: </li></ul><ul><ul><li> Phải “ nhúng ” mã nhị phân kèm theo chương trình khi liên kết, dẫn đến tình trạng tốn không gian đĩa nếu như có chương trình yêu cầu sử dụng một hàm nhiều lần (ví dụ như hàm printf() ) </li></ul></ul><ul><ul><li> Phải biên dịch và/hoặc liên kết lại khi muốn nâng cấp (hoặc bổ sung tính năng mới) </li></ul></ul><ul><li>- Thư viện liên kết động khắc phục được hai vấn đề trên do các hàm thư viện liên kết động được nạp trong thời gian thi hành và có thể được dùng chung giữa nhiều tiến trình. </li></ul><ul><li>Để đưa hàm vào thư viện liên kết động  cần dùng tùy chọn -fpic (hoặc –fPIC), viết tắt của Position Independence Code </li></ul>
  24. 24. <ul><li>- Ví dụ sau sẽ biên dịch fred.c và bill.c thành các tập tin .o có khả năng đưa được vào thư viện liên kết động: </li></ul><ul><ul><li># gcc -c -fpic fred.c bill.c </li></ul></ul><ul><li>- Tiếp đến tạo thư viện liên kết động từ các file đối tượng “ .o ” trên bằng cách sử dụng tùy chọn “ -shared ” (do thư viện liên kết động được tạo phụ thuộc vào kiến trúc của HĐH): </li></ul><ul><ul><li># gcc -shared bill.o fred.o -o libfoo.so </li></ul></ul><ul><li>- Cách sử dụng thư viện liên kết động với chương trình chính: </li></ul><ul><ul><li># gcc program.c -o program -L. -lfoo </li></ul></ul><ul><li>- Với các tuỳ chọn “ -L. ” và “-lfoo” trình biên dịch và liên kết gcc sẽ tìm thư viện libfoo.so hoặc libfoo.a trong thư mục hiện hành và tạo ra file thực thi program. </li></ul><ul><li>- Thư viện “ .so ” được ưu tiên sử dụng so với “.a” . Nếu không tìm thấy file thư viện “ .so ” trên thì “ .a ” mới được xem xét đến. </li></ul>
  25. 25. Ví dụ minh họa về thư viện liên kết trên Windows ==  -----  -----  ==
  26. 26. <ul><ul><ul><li>4.8.2.2. Thục thi gọi liên kết muộn </li></ul></ul></ul><ul><li>Thư viện liên kết động phải nằm trong /lib, /usr/lib, /usr/local/lib hoặc thư mục với đường dẫn chỉ bởi biến môi trường LD_LIBRARY_PATH </li></ul><ul><li>Ví dụ: </li></ul><ul><li># export LD_LIBRARY_PATH=/myprog/lib:/other/lib:. </li></ul><ul><li># ./program </li></ul><ul><li>Có thể chủ động gọi và nạp các hàm thư viện liên kết động mà không cần nhờ vào HĐH. Đây được gọi là “ hàm liên kết muộn ” </li></ul><ul><li>Ba hàm liên kết muộn chính là: </li></ul><ul><ul><li> dlopen() </li></ul></ul><ul><ul><li> dlsym() </li></ul></ul><ul><ul><li>dlclose() </li></ul></ul>
  27. 27. - Các hàm trên được khai báo như sau: #include <dlfcn.h> void *dlopen (const char* lib_file, int mode); void *dlsym (void * handle, const char* funct_name); int dlclose (void *handle); - Hàm dlopen() yêu cầu đường dẫn lib_file tới thư viện “.so” cần nạp. - Hàm dlsym() yêu cầu con trỏ đến thư viện nạp và trả về trước đó bởi hàm dlopen() - Hàm dlclose() giải phóng thư viện trỏ đến bởi handle do dlopen() nạp trước đó - Tham khảo Ví dụ 4-6: program2.c
  28. 28. <ul><li>Chân thành cảm ơn </li></ul><ul><ul><li>Các anh/chị đã tham dự bài giảng. </li></ul></ul><ul><ul><li>Bộ phận Multi-media đã hỗ trợ chúng tôi trong quá trình thuyết giảng. </li></ul></ul>Kết thúc chương 4 Hẹn gặp lại buổi học kế
  29. 29. Chương 5: Xử lý tập tin và thư mục <ul><li>Bao gồm các phần sau: </li></ul><ul><ul><li>Hệ thống t ập tin trong Linux </li></ul></ul><ul><ul><li>Các cách xử lý tập tin trong Linux </li></ul></ul><ul><ul><li>Thư viện xuất nhập chuẩn (Standard I/O Library) </li></ul></ul><ul><ul><li>Hàm truy xuất cấp thấp </li></ul></ul><ul><ul><li>Xử lý thư mục </li></ul></ul>CITD - VNUHCM
  30. 30. <ul><li>5.1. Hệ thống tập tin trong Linux </li></ul><ul><li>Tất cả các tập tin và thư mục được tổ chức theo dạng cây duy nhất </li></ul><ul><li>Gốc của cây thư mục gọi là root và được ký hiệu là “ / ” </li></ul><ul><li>Cho dù máy tính có nhiều ổ đĩa (hoặc nhiều phân vùng, nhiều thiết bị)  tất cả được kết gán vào các nhánh của cây thư mục chính </li></ul><ul><li>Thao tác kết gán được thực hiện bởi lệnh mount </li></ul><ul><li>Hình 5-1 cho thấy thư mục /home/soft là thư mục được gán kết với một phân vùng của Đĩa cứng thứ 2 </li></ul>
  31. 31. - Thực tế, thư mục trong Linux được xem như một tập tin có thuộc tính “ d ”. Hình 5.1 Hệ thống thư mục trong Linux Đĩa cứng 1 Đĩa cứng 2 usr etc home dev minhkhai soft book.doc office helps.txt
  32. 32. Hình 5.1.a Một cấu trúc thư mục trong Linux
  33. 33. <ul><li>5.2. Các cách xử lý tập tin trong Linux </li></ul><ul><li>Có hai cách truy xuất file: </li></ul><ul><ul><li> Truy xuất file sử dụng vùng đệm (stream file): Dựa vào các hàm thư viện chuẩn stdio </li></ul></ul><ul><ul><li> Truy xuất file cấp thấp (low-level): Dựa vào các lời gọi hệ thống </li></ul></ul><ul><li>- Hình 5.2 là mô hình truy xuất phần cứng dựa vào thư viện chuẩn và các lời gọi hệ thống. </li></ul>
  34. 34. Hình 5.2 Cách triệu gọi và truy xuất thiết bị phần cứng Ứng dụng (Application) stdio Library Lời gọi hệ thống (System Call) KERNEL Device Drivers Thiết bị phần cứng (Hardware Devices) gọi hàm Không gian người dùng (User Space) Không gian hệ thống (Kernel Space)
  35. 35. <ul><li>5.3. Thư viện xuất nhập chuẩn (Standard I/O Library) </li></ul><ul><li>Được khai báo trong stdio.h </li></ul><ul><li>Thư viện này tuân theo chuẩn ANSI  có thể sử dụng chúng hầu như trên các HĐH. </li></ul><ul><ul><li> fopen(), fclose() </li></ul></ul><ul><ul><li> fread(), fwrite() </li></ul></ul><ul><ul><li> fflush() </li></ul></ul><ul><ul><li> fseek() </li></ul></ul><ul><ul><li> v.v... </li></ul></ul><ul><li>- Tất cả các hàm trên đều sử dụng con trỏ tới cấu trúc FILE </li></ul><ul><li>5.3. Thư viện xuất nhập chuẩn (Standard I/O Library) </li></ul><ul><li>Được khai báo trong stdio.h </li></ul><ul><li>Thư viện này tuân theo chuẩn ANSI  có thể sử dụng chúng hầu như trên các HĐH khác nhau: </li></ul><ul><ul><li> fopen(), fclose() </li></ul></ul><ul><ul><li> fread(), fwrite() </li></ul></ul><ul><ul><li> fflush() </li></ul></ul><ul><ul><li> fseek() </li></ul></ul><ul><ul><li> v.v... </li></ul></ul><ul><li>- Tất cả các hàm trên đều sử dụng con trỏ tới cấu trúc FILE </li></ul>
  36. 36. 5.3.1. Đóng mở tập tin - Sử dụng hàm fopen() và fclose() - Ví dụ: /*Khai b á o c ác b iế n con tr ỏ t ới c ấ u tr ú c FILE*/ FILE * f_read; FILE * f_write; FILE * f_readwrite; FILE * f_append; /*M ở t ập tin data.txt để đọ c*/ f_read=fopen(“/home/ch12/data.txt”, “r”); if (!f_read) { /*Kh ô ng m ở đượ c t ập tin */ perror(“Khong mo duoc file de doc...”); exit (1); }
  37. 37. /* M ở t ập tin logfile trong th ư m ụ c hi ện h à nh để ghi. N ế u ch ưa có, t ập tin mới được tạo; N ế u đã có, n ội dung cũ bị xóa */ f_write=fopen(“logfile.txt”, “w”); /* M ở /usr/local/db/users để đọc và ghi */ f_readwrite=fopen(“/usr/local/db/users”, “rw”); /* M ở /var/adm/messages để nối thêm dữ liệu vào cuối */ f_append=fopen(“/var/adm/messages”, “a”); /* Đóng tập tin đang mở */ if (!fclose(f_readwrite)) { perror(“Khong the dong file duoc...”); exit (1); }
  38. 38. 5.3.2. Đọc từ tập tin - Sau khi mở tập tin và có con trỏ đến cấu trúc FILE, có thể thực hiện việc đọc dữ liệu bằng nhiều hàm thư viện. - Ví dụ: int c; char buf[200]; c=fgetc(f_read); // Đọc 1 ký tự hoặc được EOF if (fread(buf, 120, 1, f_read) != 1) { // Đọc 1 khối ký tự perror(“Không đọc được !”); } if (feof(f_read)){ printf(“Gặp EOF !”); }
  39. 39. 5.3.3. Ghi vào tập tin - Giả sử f_readwrite là con trỏ đến cấu trúc FILE đã được fopen() với chế độ ghi là “w”. - Ví dụ: int c; char buf[201]; // Ghi ký tự ‘a’ ra tập tin c=‘a’; fputc(f_readwrite); // Ghi một chuỗi ký tự ra tập tin strcpy(buf, “Hello World !”); fputs(buf, f_readwrite); // Đẩy dữ liệu còn lại trong vùng đệm ra tập tin fflush(f_readwrite);
  40. 40. 5.3.4. Di chuyển vị trí đọc/ghi trong tập tin - Dùng hàm fseek() phối hợp với ftell(). - Ví dụ: fseek(f_read, 20L, SEEK_SET); // Chuyển đến vị trí 20 fseek(f_read, 10L, SEEK_CUR); // Đi 10 vị trí tính từ vị trí hiện thời // Ghi nhớ vị trí hiện thời. Chuyển đến vị trí cách cuối file 50 byte // Ghi chuỗi Hello World ! kể từ vị trí đó, sau đó về chỗ cũ long old_position=ftell(f_readwrite); if (fseek(f_readwrite, -50L, SEEK_END) < 0){ perror(“Không chuyển đến được !”); exit(1); } fputs(“Hello World !”, f_readwrite); fseek(f_readwrite, old_position, SEEK_SET) ;
  41. 41. <ul><li>5.4. Hàm truy xuất cấp thấp </li></ul><ul><li>Số mô tả (File Descriptor) được dùng để tham chiếu tới tập tin. </li></ul><ul><li>5.4.1. Đọc/ghi tập tin </li></ul><ul><li>#include <fcntl.h> </li></ul><ul><li>#include <sys/types.h> </li></ul><ul><li>#include <sys/stat.h> </li></ul><ul><li>#include <unistd.h> </li></ul><ul><li>// Các biến chứa số mô tả tập tin trả về bởi hàm open() </li></ul><ul><ul><li>in t fd_read; </li></ul></ul><ul><ul><li>in t fd_write; </li></ul></ul><ul><ul><li>int fd_readwrite; </li></ul></ul><ul><ul><li>int fd_append; </li></ul></ul>
  42. 42. <ul><ul><li>size_t rc; </li></ul></ul><ul><ul><li>char buf[20]; </li></ul></ul><ul><ul><ul><li>fd_read=open(“/data/vb1.txt”, O_RDONLY); </li></ul></ul></ul><ul><ul><ul><li>rc=read(fd_read, buf, 20); // Đọc 20 bytes </li></ul></ul></ul><ul><ul><ul><li>if (rc == 0){ </li></ul></ul></ul><ul><ul><ul><li>printf(“Gặp EOF”); </li></ul></ul></ul><ul><ul><ul><li>} </li></ul></ul></ul><ul><ul><ul><li>else if (rc < 0){ </li></ul></ul></ul><ul><ul><ul><li>perror(“Không đọc được !”); </li></ul></ul></ul><ul><ul><ul><li>exit(1); </li></ul></ul></ul><ul><ul><ul><li>} </li></ul></ul></ul><ul><ul><ul><li>else { </li></ul></ul></ul><ul><ul><ul><li>printf(“Đọc được %d bytes”, rc); </li></ul></ul></ul><ul><ul><ul><li>} </li></ul></ul></ul><ul><ul><ul><li>close(fd_read); </li></ul></ul></ul>
  43. 43. <ul><ul><ul><li>fd_readwrite=open(“/data/food.db”, O_RDWR); </li></ul></ul></ul><ul><ul><ul><li>if (fd_readwrite < 0){ </li></ul></ul></ul><ul><ul><ul><li>perror(“Không mở được !”); </li></ul></ul></ul><ul><ul><ul><li>exit(1); </li></ul></ul></ul><ul><ul><ul><li>} </li></ul></ul></ul><ul><ul><ul><li>rc=write(fd_readwrite, “Hello World !”, strlen(“Hello World !”)) </li></ul></ul></ul><ul><ul><ul><li>if (rc < 0){ </li></ul></ul></ul><ul><ul><ul><li>perror(“Không ghi được !”); </li></ul></ul></ul><ul><ul><ul><li>exit(2); </li></ul></ul></ul><ul><ul><ul><li>} </li></ul></ul></ul><ul><ul><ul><li>close(fd_readwrite); </li></ul></ul></ul>
  44. 44. <ul><ul><li>5.4.2. Kiểm tra quyền trên tập tin </li></ul></ul><ul><ul><li>Hàm access() dùng kiểm tra quyền truy cập tập tin: </li></ul></ul><ul><ul><li>#include <unistd.h> </li></ul></ul><ul><ul><li>// Kiểm tra quyền đọc/ghi </li></ul></ul><ul><ul><li>if (access(“/data/data.db”, R_OK | W_OK) == 0) </li></ul></ul><ul><ul><li>printf(“Có quyền Đọc-Ghi”); </li></ul></ul><ul><ul><li>else </li></ul></ul><ul><ul><li>printf(“Không có quyền Đọc-Ghi”); </li></ul></ul>
  45. 45. <ul><ul><li>5.4.3. Thiết lập quyền trên tập tin </li></ul></ul><ul><ul><li>Hàm chmod() dùng để thiết lập quyền truy cập tập tin: </li></ul></ul><ul><ul><li>#include <sys/types.h> </li></ul></ul><ul><ul><li>#include <sys/stat.h> </li></ul></ul><ul><ul><li>// Cho phép Chủ sở hữu quyền Đọc-Ghi </li></ul></ul><ul><ul><li>// Cho phép Nhóm được Đ ọc, còn những người Khác được quyền Ghi </li></ul></ul><ul><ul><li>i f (chmod(“/data/data.db”, S_IRUSR | S_IWUSR|S_IRGRP|S_IWOTH) == -1){ </li></ul></ul><ul><ul><li>perror(“Không thiết lập quyền được !”); </li></ul></ul><ul><ul><li>else </li></ul></ul><ul><ul><li>printf(“Thiết lập quyền được ”); </li></ul></ul>
  46. 46. <ul><ul><li>5.4.4. Lấy thông tin về tập tin </li></ul></ul><ul><ul><li>Hàm stat() dùng để lấy thông tin về tập tin: </li></ul></ul><ul><ul><li>#include <unistd.h> </li></ul></ul><ul><ul><li>#include <sys/types.h> </li></ul></ul><ul><ul><li>#include <sys/stat.h> </li></ul></ul><ul><ul><li>struct stat file_status; </li></ul></ul><ul><ul><li>i f (stat(“/data/data.db”, &file_status) == 0){ </li></ul></ul><ul><ul><li>if (S_ISDIR(file_status.st_mode)) printf(“Thư mục !”); </li></ul></ul><ul><ul><li>if (S_ISLNK(file_status.st_mode)) printf(“Soft Link !”); </li></ul></ul><ul><ul><li>if (S_ISREG(file_status.st_mode)) printf(“Normal File!”); </li></ul></ul><ul><ul><li>} </li></ul></ul><ul><ul><li>else perror(“Không xác định được trạng thái !”) </li></ul></ul>
  47. 47. <ul><ul><li>5.4.5. Đổi tên tập tin </li></ul></ul><ul><ul><li>#include <stdio.h> </li></ul></ul><ul><ul><li>if (rename(“/data/data.db”, “/data/data.bak”) == -1){ </li></ul></ul><ul><li>perror(“Không đổi tên được !”) </li></ul><ul><li>} </li></ul><ul><ul><li>5.4.6. Xóa tập tin </li></ul></ul><ul><ul><li>#include <unistd.h> </li></ul></ul><ul><ul><li>if (unlink(“/data/data.db”) == -1){ </li></ul></ul><ul><li>perror(“Không xóa được !”) </li></ul><ul><li>} </li></ul>
  48. 48. <ul><ul><li>5.4.7. Tạo liên kết mềm </li></ul></ul><ul><ul><li>#include <unistd.h> </li></ul></ul><ul><ul><li>i f (symlink(“/data/data.db”, “/luu/data.lnk”) == -1){ </li></ul></ul><ul><li>perror(“Không tạo được liên kết mềm !”) </li></ul><ul><li>} </li></ul><ul><ul><li>5.4.8. Tạo liên kết cứng </li></ul></ul><ul><ul><li>#include <unistd.h> </li></ul></ul><ul><ul><li>i f (link(“/data/data.db”, “/luu/data.db”) == -1){ </li></ul></ul><ul><li>perror(“Không tạo được liên kết cứng !”) </li></ul><ul><li>} </li></ul>
  49. 49. 5.5. Xử lý thư mục Linux có các hàm riêng dùng để xử lý thư mục: #include <sys/types.h> #include <dirent.h> // Mở thư mục với kết quả là con trỏ tới cấu trúc DIR DIR *opendir(const char * name); // Đọc một đầu mục struct dirent readdir(DIR *dirp); // Đóng thư mục int closedir(DIR *dirp); // Vị trí hiện hành của con trỏ đầu mục long int telldir(DIR *dirp);
  50. 50. <ul><li>// Chuyển đến đầu mục theo số hiệu </li></ul><ul><li>long int seekdir(DIR *dirp, long int loc); </li></ul><ul><li>// Tạo thư mục </li></ul><ul><ul><li>#include <sys/types.h> </li></ul></ul><ul><ul><li>#include <sys/stat.h> </li></ul></ul><ul><li>int mkdir(const char *path, mode_t mode); </li></ul><ul><li>// Xóa thư mục </li></ul><ul><li>#include <unistd.h> </li></ul><ul><li>int rmdir(const char *path); </li></ul><ul><li>// Chuyển đổi thư mục làm việc </li></ul><ul><li>int chdir(const char *path); </li></ul><ul><li>// Nhận đường dẫn của thư mục làm việc (hiện thời) </li></ul><ul><li>char *getcwd(char *buff, size_t size); </li></ul>
  51. 51. <ul><li>Ví dụ: </li></ul><ul><li>#include <unistd.h> </li></ul><ul><li>#include <dirent.h> </li></ul><ul><ul><li>#include <sys/types.h> </li></ul></ul><ul><ul><li>#include <sys/stat.h> </li></ul></ul><ul><li>DIR *dp; struct dirent *entry; struct stat statbuf; </li></ul><ul><li>if ((dp = opendir(“/data”)) == NULL){ </li></ul><ul><li>perror(“Không mở được thư mục”); exit(1); </li></ul><ul><li>} </li></ul><ul><li>while ((entry = readdir(dp)) != NULL){ </li></ul><ul><li>stat(entry->d_name, &statbuf); </li></ul><ul><li>if (S_ISDIR(statbuf.st_mode)){ /* Là thư mục con */} </li></ul><ul><li>else {/* Là tập tin */}; </li></ul><ul><li>} </li></ul><ul><li>closedir(dp); </li></ul>
  52. 52. Chương 6: Tương tác với môi trường Linux <ul><li>Bao gồm các phần sau: </li></ul><ul><ul><li>Đối số truyền cho chương trình </li></ul></ul><ul><ul><li>Bi ến môi trường </li></ul></ul><ul><ul><li>Th ời gian và ngày tháng </li></ul></ul>CITD - VNUHCM
  53. 53. 6.1. Đối số truyền cho chương trình 6.1.1. Phân tích đối số dòng lệnh Chuơng trình chính viết bằng C có thể chứa hàm main() với đặc tả: int main(int argc, char *argv[]) Đối số trên dòng lệnh thường dùng để truyền thông tin từ ngoài vào: # args –i –lrv ‘Hi Linux’ –f “/data/vb.txt” Chương trình sau in ra tất cả các giá trị đối số mà hàm main() nhận được:
  54. 54. <ul><li>#include <stdio.h> </li></ul><ul><li>int main(int argc, char *argv[]) </li></ul><ul><li>{ </li></ul><ul><li>int arg; </li></ul><ul><li>for(arg = 0; arg < argc; arg++) { </li></ul><ul><li>if(argv[arg][0] == '-') </li></ul><ul><li>printf(&quot;option: %sn&quot;, argv[arg]+1); </li></ul><ul><li>else </li></ul><ul><li>printf(&quot;argument %d: %sn&quot;, arg, argv[arg]); </li></ul><ul><li>} </li></ul><ul><li>return(0); </li></ul><ul><li>} </li></ul>
  55. 55. 6.1.2. Hàm getopt() Hữu ích cho việc phân tích đối số dòng lệnh. Ví dụ: getopt(argc, argv, “if:lr”); sẽ phân tích và xem –i, -l, -r, -f là các tùy chọn, trong đó –f có dữ liệu kèm theo. #include <stdio.h> #include <unistd.h> int main(int argc, char *argv[]) { int opt;
  56. 56. while ((opt = getopt(argc, argv, &quot;if:lr&quot;)) != -1) { switch (opt) { case 'i': case 'l': case 'r': printf(&quot;option: %cn&quot;, opt); break ; case 'f': printf(&quot;filename: %sn&quot;, optarg); break ; case ':': printf(&quot;option needs a valuen&quot;); break ;
  57. 57. case '?': printf(&quot;unknown option: %cn&quot;, optopt); break ; } } for (; optind < argc; optind++) printf(&quot;argument: %sn&quot;, argv[optind]); return (0); }
  58. 58. 6.2. Biến môi trường Truy xuất và thiết lập biến môi trường bằng các hàm: #include <stdlib.h> char *getenv(const char *name); int putenv(const char *string); Trong đó, name chứa tên biến môi trường cần truy xuất, string chứa chuỗi theo mẫu: varname=value
  59. 59. 6.3. Thời gian và ngày tháng - Lấy về giá trị thời gian ở cấp thấp (số giây kể từ 0 giờ 1970) bằng hàm time(): #include <time.h> time_t time(time_t *loc); Trong đó, loc là tham biến dùng nhận kết quả trả về của hàm - So sánh giữa 2 thời điểm bằng hàm difftime(): #include <time.h> double difftime(time_t time1, time_t time2);
  60. 60. - Hàm gmtime() dùng truy xuất ngày/tháng/năm và giờ cụ thể: #include <time.h> struct tm *gmtime(const time_t timeval); Ví dụ: #include <time.h> #include <stdio.h> int main() { struct tm *tm_ptr; time_t the_time;
  61. 61. (void) time(&the_time); tm_ptr = gmtime(&the_time); printf(&quot;Raw time is %ldn&quot;, the_time); printf(&quot;gmtime gives:n&quot;); printf(&quot;date: %02d/%02d/%02dn&quot;, tm_ptr->tm_year, tm_ptr->tm_mon, tm_ptr->tm_mday); printf(&quot;time: %02d:%02d:%02dn&quot;, tm_ptr->tm_hour, tm_ptr->tm_min, tm_ptr->tm_sec); return (0); }
  62. 62. <ul><li>Chân thành cảm ơn </li></ul><ul><ul><li>Các anh/chị đã tham dự bài giảng. </li></ul></ul><ul><ul><li>Bộ phận Multi-media đã hỗ trợ chúng tôi trong quá trình thuyết giảng. </li></ul></ul>Kết thúc chương 6 Hẹn gặp lại buổi học kế

×