Nội dung của tài liệu trình bày về chương trình trên Linux, các tập tin tiêu đề (header), các tập tin thư viện, thư viện liên kết trên trên Linux, thư viện liên kết tĩnh và thư viện liên kết động, nội dung của bài thực hành số 2, viết chương trình C in ra màn hình các số nguyên từ 0 đến 9, viết chương trình cộng và nhân 2 số nguyên sử dụng thư viện liên kết tĩnh, viết chương trình cộng và nhân 2 số nguyên sử dụng thư viện liên kết động và một số bài tập thêm.
Bài 2: LẬP TRÌNH C TRÊN LINUX I Lý thuyết Chương trình Linux - Để viết chương trình Linux, cần phải nắm rõ số vị trí tài nguyên để xây dựng chương trình trình biên dịch, tập tin thư viện, tập tin tiêu đề (header), tập tin chương trình sau biên dịch, … - Trình biên dịch gcc thường đặt thư mục /usr/bin /usr/local/bin (kiểm tra lệnh which gcc) Tuy nhiên, biên dịch, gcc cần đến nhiều tập tin hỗ trợ nằm thư mục khác tập tin tiêu đề (header) C thường nằm thư mục /usr/include hay /usr/local/include Các tập tin thư viện liên kết thường gcc tìm thư mục /lib /usr/local/lib Các thư viện chuẩn gcc thường đặt thư mục /usr/lib/gcc-lib Chương trình sau biên dịch tập tin thực thi (dạng nhị phân) đặt vị trí hệ thống Các tập tin tiêu đề (header) - Các tập tin tiêu đề C thường định nghĩa hàm khai báo cần thiết cho trình biên dịch Hầu hết chương trình Linux biên dịch sử dụng tập tin tiêu đề thư mục /usr/include thư mục bên thư mục này, ví dụ: /usr/include/sys Một số khác trình biên dịch dị tìm mặc định /usr/include/X11 khai báo hàm lập trình đồ họa X-Window, /usr/include/g++-2 trình biên dịch GNU g++ Tuy nhiên, có tập tin tiêu đề riêng thư mục khác thư mục mặc định hệ thống rõ tường minh đường dẫn đến thư mục biên dịch tùy chọn –I, ví dụ: $ gcc –I/usr/mypro/include test.c –otest - Khi sử dụng hàm thư viện hệ thống chương trình C, ngồi việc phải biết khai báo nguyên mẫu hàm, cần phải biết hàm định nghĩa tập tin tiêu đề Trình man cung cấp cho thơng tin chi tiết Ví dụ, dùng man để tham khảo thông tin hàm kill(), thấy cần phải khai báo tập tin tiêu đề types.h signal.h Các tập tin thư viện - Các tập tin tiêu đề C cần thiết để trình biên dịch bắt lỗi cú pháp, kiểm tra kiểu liệu chương trình tạo tập tin đối tượng Muốn tạo chương trình thực thi, cần phải có tập tin thư viện Trong Linux, tập tin thư viện tĩnh C có phần mở rộng a, so, sa bắt đầu tiếp đầu ngữ lib Ví dụ libutil.a hay libc.so tên thư viện liên kết Linux - Linux có hai loại liên kết liên kết tĩnh (static) liên kết động (dynamic) Thư viện liên kết động Linux thường có phần mở rộng so, dùng lệnh ls /usr/lib ls /lib để xem thư viện hệ thống sử dụng Khi biên dịch, thơng thường trình liên kết (ld) tìm thư viện thư viện chuẩn /usr/lib /lib Để định tường minh thư viện đó, làm sau: $ gcc test.c –otest /usr/lib/libm.a Bởi thư viện bắt buộc phải có tiếp đầu ngữ lib có phần mở rộng a so, trình biên dịch cho phép sử dụng tùy chọn –l ngắn gọn sau: $ gcc test.c –otest -lm thấy gcc mở rộng –l thành tiếp đầu ngữ lib tìm libm.a libm.so thư mục chuẩn để liên kết - Mặc dù vậy, lúc thư viện phải nằm thư viện Linux Nếu thư viện nằm thư mục khác, định gcc tìm kiếm trực tiếp với tùy chọn –L sau: $ gcc test.c –otest -L/usr/myproj/lib -ltool Lệnh cho phép liên kết với thư viện libtool.a libtool.so thư mục /usr/myproj/lib Thư viện liên kết Linux - Hình thức đơn giản thư viện tập hợp tập tin o trình biên dịch tạo bước biên dịch với tùy chọn –c Ví dụ $gcc –c helloworld.c trình biên dịch chưa tạo tập tin thực thi mà tạo tập tin đối tượng helloworld.o Tập tin chứa mã máy chương trình xếp lại Nếu muốn tạo tập tin thực thi, gọi trình biên dịch thực bước liên kết: $gcc helloworld.o –o helloworld Trình biên dịch gọi tiếp trình liên kết ld tạo định dạng tập tin thực thi cuối Ở đây, không sử dụng tùy chọn –c, trình biên dịch thực hai bước đồng thời a) Thư viện liên kết tĩnh - Thư viện liên kết tĩnh thư viện liên kết trình biên dịch lấy tồn mã thực thi hàm thư viện đưa vào chương trình Chương trình sử dụng thư viện liên kết tĩnh chạy độc lập với thư viện sau biên dịch xong Nhưng nâng cấp sửa đổi, muốn tận dụng chức thư viện phải biên dịch lại chương trình Ví dụ sử dụng liên kết tĩnh: /* cong.c */ int cong( int a, int b ) { return a + b; } /* nhan.c */ long nhan( int a, int b ) { return a * b; } Thực biên dịch để tạo hai tập tin thư viện đối tượng o $ gcc –c cong.c nhan.c Để chương trình gọi hàm thư viện trên, cần tạo tập tin header h khai báo nguyên mẫu hàm để người sử dụng triệu gọi: /* lib.h */ int cong( int a, int b ); long nhan( int a, int b ); Cuối cùng, tạo chương trình program.c triệu gọi hai hàm /* program.c */ #include #include "lib.h" int main () { int a, b; printf( "Nhap vào a : " ); scanf( "%d", &a ); printf("Nhap vào b : " ); scanf( "%d", &b ); printf( "Tổng %d + %d = %d\n", a, b, cong( a, b ) ); printf( "Tich %d * %d = %ld\n", a, b, nhan( a, b ) ); return ( ); } - Chúng ta biên dịch liên kết với chương trình sau: $ gcc –c program.c $ gcc program.o cong.o nhan.o -oprogram Sau thực thi chương trình $ /program Ở o tập tin thư viện đối tượng Các tập tin thư viện a chứa tập hợp tập tin o Tập tin thư viện a thực dạng tập tin nén tạo chương trình ar Chúng ta yêu cầu ar đóng cong.o nhan.o vào libfoo.a $ ar cvr libfoo.a cong.o nhan.o Sau có thư viện libfoo.a, liên kết lại với chương trình theo cách sau: $ gcc program.o –oprogram libfoo.a Chúng ta sử dụng tùy chọn –l để định thư viện biên dịch thay cho cách Tuy nhiên libfoo.a không nằm thư mục thư viện chuẩn, cần phải kết hợp với tùy chọn –L để định đường dẫn tìm kiếm thư viện thư mục hành Dưới cách biên dịch: $ gcc program.c –oprogram –L –lfoo Chúng ta sử dụng lệnh nm để xem hàm biên dịch sử dụng tập tin chương trình, tập tin đối tượng o tập tin thư viện a Ví dụ: $ nm cong.o b) Thư viện liên kết động - Khuyết điểm thư viện liên kết tĩnh nhúng mã nhị phân kèm theo chương trình biên dịch, tốn khơng gian đĩa khó nâng cấp Thư viện liên kết động dùng để giải vấn đề Các hàm thư viện liên kết động khơng trực tiếp đưa vào chương trình lúc biên dịch liên kết, trình liên kết lưu thơng tin tham chiếu đến hàm thư viện liên kết động Vào lúc chương trình nhị phân thực thi, Hệ Điều Hành nạp chương trình liên kết cần tham chiếu vào nhớ Như vậy, nhiều chương trình sử dụng chung hàm thư viện - Tạo thư viện liên kết động: Khi biên dịch tập tin đối tượng để đưa vào thư viện liên kết động, phải thêm tùy chọn – fpic (PIC- Position Independence Code – mã lệnh vị trí độc lập) Ví dụ: biên dịch lại tập tin cong.c nhan.c $ gcc –c –fpic cong.c nhan.c Để tạo thư viện liên kết động, khơng sử dụng trình ar với thư viện liên kết tĩnh mà dùng lại gcc với tùy chọn –shared $ gcc –shared cong.o nhan.o -olibfoo.so Nếu tập tin libfoo.so có sẵn trước khơng cần dùng đến tùy chọn –o $ gcc –shared cong.o nhan.o libfoo.so Bây có thư viện liên kết động libfoo.so Biên dịch lại chương trình sau: $ gcc program.c –oprogram –L –lfoo - Sử dụng thư viện liên kết động: Khi Hệ Điều Hành nạp chương trình program, cần tìm thư viện libfoo.so hệ thống Ngồi thư mục chuẩn, Linux cịn tìm thư viện liên kết động đường dẫn biến môi trường LD_LIBRARY_PATH Do libfoo.so đặt thư mục hành, không nằm thư mục chuẩn nên ta cần đưa thư mục hành vào biến môi trường LD_LIBRARY_PATH: $ LD_LIBRARY_PATH=.: $ export LD_LIBRARY_PATH Kiểm tra xem Hệ Điều Hành tìm tất thư viện liên kết động mà chương trình sử dụng hay khơng: $ ldd program chạy chương trình sử dụng thư viện liên kết động này: $./program - Một khuyết điểm việc sử dụng thư viện liên kết động thư viện phải tồn đường dẫn để Hệ Điều Hành tìm chương trình triệu gọi Nếu khơng tìm thấy thư viện, Hệ Điều Hành chấm dứt chương trình cho dù hàm thư viện chưa sử dụng Ta chủ động nạp gọi hàm thư viện liên kết động mà không cần nhờ vào Hệ Điều Hành cách gọi hàm liên kết muộn II Nội dung thực hành số 1.Viết chương trình C in hình các số nguyên từ đến Bước 1: Mở chương trình soạn thảo: $vi thuchanh.c Bước 2: Viết chương trình: - Khởi đầu vào hình vi bạn chế độ xem (view) Muốn chỉnh sửa nội dung file bạn nhấn phím Insert Dịng trạng thái cuối hình đổi thành INSERT-cho biết bạn chế độ soạn thảo (bạn nhấn phím i a thay cho phím Insert) - Nhấn Enter bạn muốn sang dịng Nhấn phím mũi tên để di chuyển trỏ thay đổi nội dung file Muốn ghi lại nội dung file sau soạn thảo, bạn nhấn Esc để trở chế độ lệnh nhấn :w Muốn thoát khỏi vi bạn nhấn :q (hoặc :wq để lưu thoát) Bước 3: Biên dịch chương trình thành tập tin đối tượng: $gcc –c thuchanh.c Bước 4: Biên dịch tập tin đối tượng thành tập tin thực thi: $gcc thuchanh.o –o thuchanh ->Lưu ý: Có thể gom bước câu lệnh: $gcc thuchanh.c –o thuchanh Bước 5: Thực thi chương trình lệnh: $./thuchanh Viết chương trình cộng nhân số nguyên sử dụng thư viện liên kết tĩnh: $ vi cong.c int cong(int a, int b) { return a + b; } $ vi nhan.c int nhan(int a, int b) { return a * b; } $ vi program.c #include int main() { int a, b; printf(“\nNhap a:”); scanf(“%d”,&a); printf(“Nhap b:”); scanf(“%d”,&b); printf(“\nTong cua hai so la: %d”,cong(a,b)); printf(“\nTich cua hai so la: %d\n”,nhan(a,b)); return 0; } $ $ $ $ gcc –c cong.c nhan.c ar cvr libfoo.a cong.o nhan.o gcc program.c –o program –L –lfoo /program Viết chương trình cộng nhân số nguyên sử dụng thư viện liên kết động: $ vi cong.c int cong(int a, int b) { return a + b; } $ vi nhan.c int nhan(int a, int b) { return a * b; } $ vi program.c #include int main() { int a, b; printf(“\nNhap a:”); scanf(“%d”,&a); printf(“Nhap b:”); scanf(“%d”,&b); printf(“\nTong cua hai so la: %d”,cong(a,b)); printf(“\nTich cua hai so la: %d\n”,nhan(a,b)); return 0; } $ $ $ $ $ $ gcc –c –fpic cong.c nhan.c gcc –shared cong.o nhan.o –o libfoo.so gcc program.c –o program –L –lfoo LD_LIBRARY_PATH=.: export LD_LIBRARY_PATH /program Bài tập thêm 4.1 Viết chương trình nhập, xuất mảng số nguyên(sử dụng thư viện liên kết động) 4.2 Tạo thư mục /home/dsl/lib - Chép thư viện libfoo.so tạo câu 4.1 vào thư mục vừa tạo - Biên dịch chạy lại chương trình ... không c? ??n nhờ vào Hệ Điều Hành c? ?ch gọi hàm liên kết muộn II Nội dung th? ?c hành số 1.Viết chương trình C in hình c? ?c số nguyên từ đến Bư? ?c 1: Mở chương trình soạn thảo: $vi thuchanh .c Bư? ?c 2: Viết... (ho? ?c :wq để lưu thốt) Bư? ?c 3: Biên dịch chương trình thành tập tin đối tượng: $gcc ? ?c thuchanh .c Bư? ?c 4: Biên dịch tập tin đối tượng thành tập tin th? ?c thi: $gcc thuchanh.o –o thuchanh -> Lưu... chọn – fpic (PIC- Position Independence Code – mã lệnh vị trí đ? ?c lập) Ví dụ: biên dịch lại tập tin cong .c nhan .c $ gcc ? ?c –fpic cong .c nhan .c Để tạo thư viện liên kết động, khơng sử dụng trình ar