1. Trang chủ
  2. » Luận Văn - Báo Cáo

Báo Cáo Bài Tập Lớn_2.Doc

23 7 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Tìm Hiểu Lập Trình C Trên Linux
Tác giả Trần Minh Phương, Bùi Long Hưng, Luân Quốc Vinh, Nguyễn Duy Hiếu
Trường học Học Viện Công Nghệ Thông Tin - [https://www.hvctt.edu.vn](https://www.hvctt.edu.vn)
Chuyên ngành Lập trình hệ điều hành
Thể loại Báo Cáo Bài Tập Lớn
Năm xuất bản 2023
Thành phố Hà Nội
Định dạng
Số trang 23
Dung lượng 285 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Báo cáo bài tập lớn BÁO CÁO BÀI TẬP LỚN MÔN NGUYÊN LÝ HỆ ĐIỀU HÀNH ĐỀ TÀI TÌM HIỂU LẬP TRÌNH C TRÊN LINUX Nhóm thực hiện Trần Minh Phương, Bùi Long Hưng, Luân Quốc Vinh, Nguyễn Duy Hiếu A Mục lục B Lờ[.]

Trang 1

BÁO CÁO BÀI TẬP LỚN MÔN: NGUYÊN LÝ HỆ ĐIỀU HÀNH

ĐỀ TÀI: TÌM HIỂU LẬP TRÌNH C TRÊN LINUX

Nhóm thực hiện : Trần Minh Phương,

Bùi Long Hưng,

Luân Quốc Vinh,

Nguyễn Duy Hiếu.

Tổng quan về bài báo cáo

Phạm vi vấn đề tìm hiểu : Tìm hiểu chung nhất xung quanh việc lập trình ngôn ngữ C trên hệ điều hành.Cách viết một chương trình C trên HĐH Linux Cách biên dịch chương trình và cài đặt

Các vấn đề liên quan : tìm hiểu về hệ điều hành linux, biết sơ lược về hệ điều hành linux cũng như những điều cơ bản về linux, đặc biết là về shell Ngoài việc biên dịch code trực tiếp bằng shell, có thể dung các IDE để biên dịch, một trong số đó là Codeblock

C Tổng quan

Trong phần báo cáo này chỉ tìm hiểu những vấn đề xung quanh vịêc lập trình C trên hệ điều

hành Linux :

 Tìm hiểu sơ qua về hệ điều hành Linux

 tổng quan về viết chương trình C, các công cụ sử dụng

 Cách biên dịch một chương trình

(Phần báo cáo này không đi sâu vào các vấn đề như cách viết lệnh hay lập trình chi chiết một chương trình mà chỉ tìm hiểu những gì chung nhất về vấn đề này Tìm hiểu các bước làm một chương trình và các quá trình được thực hiện khi lập trình C trên Linux.)

Qua phần báo cái này, có thể hiểu được them về các khái niệm trong lập trình C trên hệ điều hành Linux, có được cái nhìn tổng quan xung quanh vịêc viết chương trình

Trang 2

Công cụ được sử dụng để Lập trình C trên Linux:

Để lập trình C trên Linux, bạn cần có một số tài liệu, phương tiện để thực hiện nó:

 Cài đặt hệ điều hành Linux (Có thể có nhiều phiên bản như Redhat, Ubuntu, Knoppix…)

 Một IDE để biên dịch code: có thể là CodeBlock hay Eclipse…

D.Trình bày chi tiết phần lý thuyết - Chi tiết về lập trình C trên Linux

I Tìm hiểu chung về hệ điều hành Linux

Đặc điểm chính của HĐH Linux

Do mã nguồn Linux phân phối tự do và miễn phí, nên ngay từ đầu đã có rất nhiều nhà lập trình tham gia vào quá trình phát triển hệ thống Nhờ đó đến thời điểm hiện nay Linux là hệ điều hành hiện đại, bền vững và phát triển nhanh nhất, hỗ trợ các công nghệ mới gần như ngay lập tức Linux có tất cả các khả năng, đặc trưng cho các hệ điều hành đầy đủ tính năng dòng UNIX Xin đưa ra đây danh sách ngắn gọn những khả năng này

Nhiều tiến trình thật sự

Tất cả các tiến trình là độc lập, không một tiến trình nào được cản trở công việc của tiến trình khác Để làm được điều này nhân thực hiện chế độ phân chia thời gian của bộ xử lý trung tâm, lần lượt chia cho mỗi tiến trình một khoảng thời gian thực hiện Cách này hoàn toàn khác với chế

độ “nhiều tiến trình đẩy nha” được thực hiện trong Windows 95, khi một tiến trình phải nhường

bộ xử lý cho các tiến trình khác (và có thể làm chậm trễ rất lâu việc thực hiện)

Truy cập nhiều người dùng

Linux không chỉ là HĐH nhiều tiến trình, Linux hỗ trợ khả năng nhiềungười dùng làm việc cùng lúc Khi này Linux có thể cung cấp tất cả các tàinguyên hệ thống cho người dùng làm việc qua các terminal ở xa khác nhau

Swap bộ nhớ lên đĩa

Swap bộ nhớ cho phép làm việc với Linux khi dung lượng bộ nhớ có hạn Nội dung của một số phần (trang) bộ nhớ được ghi lên vùng đĩa cứng xác định từ trước Vùng đĩa cứng này được coi

là bộ nhớ phụ thêm vào Việc này có làm giảm tốc độ làm việc, nhưng cho phép chạy các

chương trình cần bộ nhớ dung lượng lớn mà thực tế không có trên máy tính

Tổ chức bộ nhớ theo trang

Hệ thống bộ nhớ Linux được tổ chức ở dạng các trang với dung lượng 4K Nếu bộ nhớ đầy, thì HĐH sẽ tìm những trang bộ nhớ đã lâu không được sử dụng để chuyển chúng từ bộ nhớ lên đĩa cứng Nếu có trang nào đó trong số những trang này lại trở thành cần thiết, thì Linux sẽ phục hồi chúng từ đĩa cứng (vào bộ nhớ) Một số hệ thống Unix cũ và một số hệ thống hiện đại (bao gồm

cả Microsoft Windows) chuyển lên đĩa tất cả nội dung của bộ nhớ thuộc về những ứng dụng không làm việc tại thời điểm hiện thời (tức là TẤT CẢ các trang bộ nhớ thuộc về ứng dụng sẽ được lưu lên đĩa khi không đủ bộ nhớ) và như vậy kém hiệu quả hơn

Nạp môđun thực hiện “theo yêu cầu”

Trang 3

Nhân Linux hỗ trợ việc cung cấp các trang bộ nhớ theo yêu cầu, khi này chỉ phần mã cần thiết của chương trình mới nằm trong bộ nhớ, còn những phần mã không sử dụng tại thời điểm hiện tại thì nằm lại trên đĩa

Cùng sử dụng chương trình

Nếu cần chạy một lúc nhiều bản sao của cùng một ứng dụng nào đó6, thì Linux chỉ nạp vào bộ nhớ một bản sao của mã chương trình và tất cả các tiến trình giống nhau cùng sử dụng một mã này

Thư viện chung

Thư viện – bộ các quá trình (thao tác) được chương trình dùng để làm việc với dữ liệu Có một

số thư viện tiêu chuẩn được dùng cùng lúc cho vài tiến trình Trên các hệ thống cũ những thư viện đó nằm trong mỗi tập tin chương trình, và thực hiện cùng lúc những chương trình này dẫn đến hao hụt bộ nhớ không đáng có Trên các hệ thống mới (bao gồm Linux) có hỗ trợ làm việc với các thư viện động (dynamic) và tĩnh (static) được chia ra, và như vậy cho phép giảm kích thước bộ nhớ bị ứng dụng chiếm

Bộ đệm động của đĩa

Bộ đệm của đĩa đó là một phần bộ nhớ của hệ thống dùng làm nơi lưu những dữ liệu thường dùng của đĩa, nhờ đó nâng cao rất nhiều tốc độ truy cập tới những chương trình và tiến trình thường dùng Người dùng MS-DOS sẽ nhớ đến chương trình SmartDrive, chương trình này dự trữ một phần bộ nhớ có kích thước xác định để làm bộ đệm cho đĩa Linux sử dụng hệ thốngđệm linh động hơn: bộ nhớ được dự trữ cho đệm được tăng lên khi bộ nhớ không được sử dụng,

và sẽ giảm xuống khi hệ thống hay tiến trình cần nhiều bộ nhớ hơn 100% tương ứng với tiêu chuẩn POSIX 1003.1 Hỗ trợ một phần các khả năng của System V và BSD POSIX 1003.1 (Portable Operating System Interface – giao diện của hệ điều hành lưu động) đưa ra giao diện tiêu chuẩn cho các hệ thống Unix, đó là một bộ các thủ tục ngôn ngữ C Ngày nay giao diện này được tất cả các hệ điều hành mới hỗ trợ Microsoft Windows NT cũng hỗ trợ POSIX 1003.1.Linux 100% tương ứng với tiêu chuẩn POSIX 1003.1 Thêm vào đó Linux còn hỗ trợ các khả năng của System V và BSD để tăng tính tương thích System V IPC Linux sử dụng công nghệ IPC (InterProcess Communication) để trao đổi thông tin giữa các tiến trình, để sử dụng tín hiệu

và bộ nhớ chung

Khả năng chạy chương trình của HĐH khác

Trong lịch sử Linux không phải là hệ điều hành đầu tiên Người ta đã viết ra hàng loạt các chương trình ứng dụng, trong đó có cả những chương trình có ích và không đến nỗi tồi, cho các HĐH đã phát triển trước Linux, bao gồm DOS, Windows, FreeBSD và OS/2 Để chạy những chương trình như vậy dưới Linux đã phát triển các trình giả lập (emulator) cho DOS, Windows 3.1, Windows 95 và Wine Ngoài ra, còn có một loạt các chương trình tạo máy ảo7 mã nguồn mởcũng như sản phẩm thương mại: qemu, bochs, pearpc, vmware, .HĐH Linux còn có khả năng chạy chương trình dành cho bộ xử lý Intel của các hệ thống Unix khác, nếu hệ thống đáp ứngtiêu chuẩn iBCS2 (intel Binary Compatibility)

Hỗ trợ các định dạng hệ thống tập tin khác nhau

Linux hỗ trợ một số lượng lớn các định dạng hệ thống tập tin, bao gồm các hệ thống tập tin DOS

và OS/2, và cả các hệ thống tập tin mới, như reiserfs, HFS, Trong khi đó hệ thống tập tin

Trang 4

chính của Linux, được gọi là Second Extended File System (ext2fs) và Third Extended File System (ext3fs) cho phép sử dụng không gian đĩa một cách có hiệu quả.

Khả năng hỗ trợ mạng

Linux có thể gắn vào bất kỳ mạng nội bộ nào Hỗ trợ tất cả các dịch vụ Unix, bao gồm

Networked File System (NFS), kết nối từ xa (telnet, rlogin, ssh), làm việc trong các mạng

TCP/IP, truy cập dial-up qua các giao thức SLIP và PPP,v.v .Đồng thời có hỗ trợ dùng Linux

là máy chủ hoặc máy khách cho mạng khác, trong đó có chia sẻ (dùng chung, sharing) các tập tin

và in từ xa trong các mạng Macintosh, NetWare và Windows

Làm việc trên các phần cứng khác nhau

Mặc dù đầu tiên HĐH Linux được phát triển cho máy tính cá nhân (PC) trên nền tảng Intel 386/486, bây giờ nó có thể làm việc trên tất cả các bộ vi xử lý Intel bắt đầu từ 386 và kết thúc là các hệ thống nhiều bộ xử lý Pentium IV, bao gồm cả các bộ xử lý 64bit Đồng thời Linux còn làm việc trên rất nhiều bộ xử lý tương thích với Intel của các nhà sản xuất khác, như AMD Trong Internet còn có những thông báo nói rằng trên các bộ xử lý Athlon và Duron của AMD Linux còn làm việc tốt hơn so với trên Intel

Ngoài ra còn có phiên bản Linux cho các bộ xử lý khác bao gồm ARM, DEC Alpha, SUN Sparc,M68000 (Atari và Amiga), MIPS, PowerPC và những bộ xử lý khác8 Xin được nói luôn là trongcuốn sách này chúng ta chỉ xem xét trường hợp Linux cho các máy tính tương thích với IBM

II Giới thiệu qua về thư viện

Hầu như tất cả các chương trình đểu dựa liên kết tới một thư viện hoặc nhiều hơn Một vài chương trình sử dụng các hàm trong C ( như là printf hay malooc) sẽ được liên kết tới thư viện

C runtime Nếu chương trình có giao diện người dùng(GUI), nó sẽ liên kết vào thư viện

windoing Nếu chương trình của bạn dùng một cơ sở dữ liệu, người cung cấp cơ sở dữ liệu đó sẽ đưa cho bạn thư viện có thể sử dụng truy xuất một cách dễ dàng Trong mỗi một trường hợp, bạnphải quyết định xem nên chọn liên kết tới thư viện tĩnh hoặc động Nếu bạn chọn thư viện tĩnh, thì chương trình của bạn sẽ trở nên cồng kềnh hơn, và khó nâng cấp hoàn thiện hơn, nhưng dĩ nhiên là sẽ dễ triển khai hơn Nếu liên kết tới thư viện động, chương trình của bạn sẽ besmaller,

dễ nâng cấp, nhưng khó phát triển Những phần giải thích hướng dẫn liên kết cả thư viện tĩnh và động, xem xét các yếu tố để có thêm chi tiết, và đưa ra một số quy tắc chính giúp cho bạn quyết định nên chọn liên kết tới thư viện nào

1 Lưu trữ

Lưu trữ ( hay thư viện tĩnh) một cách đơn giản là lưu trữ một tập hợp các đối tượng như là một file đơn lẻ.(Lưu trữ tương đương như một file trong windows có đuôi là LIB) Khi bạn quyết định lưu trữ với liên kết, liên kết tìm kiếm trong kho trữ tìm những file đối tượng, trích chúng

ra, và liên kết chúng vào trong chương trình, với điều kiện là ngay lúc đó có các đối tượng Bạn

có tạo ra kho trữ bằng các lệnh Các file lưu trữ truyền thống sử dụng đuôi mở rộng là a.a hơn là đuôi o đã chấp nhận bởi các tệp đối tượng bình thường Ở đây bằng cách nào bạn có thể nối test1.o và test2.o thành một file lưu trữ libtes.a : % ar cr libtest.a test1.o test2.o

Các thanh cờ cr chỉ cho cách tạo ra kho trữ Khi kết nối vào kho trữ bằng lệnh, nó sẽ tìm kiếm trong kho trữ các ký hiệu đơn giản ( hàm hoặc biến số) bởi sự liên quan tới các tệp đối tượng đã

có trong quá trình nhưng chưa định nghĩa Các tệp đối tượng xác định các kí hiệu đã rút ra từ

Trang 5

kho trữ khi mà bắt gặp các lệnh Ví dị giả định test.c chứa đoạn code ở trong Listing2.7 và app.c có code ở phần Listing2.8.

Nội dung test.c

Bây giờ giả định test.o được nối với một số file đối tượng để sinh ra kho trữ libtest.o Sau đây là dòng lệnh sẽ không hoạt động:

% gcc -o app -L -ltest app.o

app.o: In function `main':

app.o(.text+0x4): undefined reference to `f'

collect2: ld returned 1 exit status

Thông báo lỗi chỉ ra là libtest.a đã không chứa định nghĩa của file, đã không có sự liên kết tới file đó Đó là bởi vì libtest.a đã được tìm kiếm khi có sự xung đột ở lần đầu tiên, và trỏ tới liên kết khác do đó đã không tham chiếu tới file được nhắc tới Trong một trường hợp khác, nếu chúng ta sử dụng các dòng, sẽ không có các thông báo lỗi được đưa ra:

% gcc -o app app.o -L ltest

Đó là lí do mà tham chiếu tới file trong app.o do đó liên kết tới cả file đối tượng test.o từ kho lưutrữ libtesr.a

2 Sự chia sẻ thư viện

Một thư viện chia sẻ ( chia sẻ các đối tượng đã biết, hoặc là các liên kết động) là liên kết những kho trữ giống nhau thành flie đối tượng Tuy nhiên, có rất nhiều sự khác biệt quan trọng Khác biệt quan trọng nhất là khi chia sẻ thư viện là liên kết tới chương trình, những thao tác có thể thực hiện được cuối cùng không chứa đựng đoạn code hiện tại ở trong thư viện chia sẻ Thay vào

đó, công việc có thể thực hiện được chỉ đơn thuần chứa chỉ tham chiếu tới thư viện chia sẻ Một vài chương trình trong hệ thống đều liên kết dựa vào những thư viện chia sẻ tương tự, chúng sẽ tham chiếu tất cả thư viện, nhưng thậm chí không có include Theo cách đó, thư viện bị “ chia sẻ” giữa tất cả các chương trình mà có liên kết tới nó

Khác biệt quan trọng thứ hai là một thư viện chia sẻ không đơn thuần chỉ là tập các file đối tượng, ngoài những mối liên kết đã chọn dùng chúng còn cần thỏa mãn những tham chiếu không xác định Thay vì, các file đối tượng được soạn thì thư viện chia sẻ được nối vào một file đối tượng đơn lẻ do đó chương trình dựa vào các liên kết ở trong thư viện chia sẻ luôn luôn bao gồm tất cả các code ở trong thư viện, hơn là các phần chia đã cần Khi tạo ra một thư viện chia sẻ, bạnphải biên dịch các đối tượng sẽ cấu tạo lên thư viện bằng cách sử dụng fPIC tùy chọn trong chương trình biên dịch, như là : % gcc -c -fPIC test1.c Tùy chọn fPIC chỉ ra chương trình biên dịch mà bạn sẽ sử dụng test.o như là một phần của sự chia sẻ đối tượng

Trang 6

Position-Independent Code (PIC)(Vị trí độc lập code)

PIC giữ vững cho Position-Independent Code Các hàm trong thư viện chia sẻ có thể nạp vào ở các địa chỉ khác nhau trong những chương trình khác nhau, do đó code ở trong đối tượng chia sẻ phải không sinh ra từ địa chỉ(hoặc vị trí) ở nơi nó nạp vào Sự cân nhắc không ảnh hưởng đến bạn, là một lập trình viên, trừ khi là bạn phải nhớ cách sử dụng cờ fPIC khi đang biên soạn codecái mà bạn muốn sử dụng ở trong thư viện chia sẻ

Khi bạn nối các file đối tượng vào trong htw viện chia sẻ, như là:

% gcc -shared -fPIC -o libtest.so test1.o test2.o

Sự tùy chọn chia sẻ chỉ ra các liên kết tạo ra thư viện chia sẻ hơn là các hoạt động có thể diễn ra bình thường Các thư viện chia sẻ sử dụng đuôi mở rộng là so Như là lưu trữ tĩnh, tên luôn luôn bắt đầu với lib chỉ ra file nào là thư viện Liên kết với thư viện chia sẻ như là liên kết với một kho trữ tĩnh Ví dụ những dòng sau đây sẽ liên kết với libtest.so nếu như nó ở trên thư mục hiện tại, hoặc một trong thư viện chuẩn tìm kiếm thư mục ở trên hệ thống:

% gcc -o app app.o -L ltest

Cho là cả libtest.a và libtest.so đều sẵn có Sau đó liên kết một thư viện hoăc không cái khác Liên kết tìm kiếm mỗi thư mục( đầu tiên lý thuyết là với –L tùy chọn, và sau đó tới thư mục chuẩn) Khi liên kết tìm tới thư mục chứa libtest.a hoặc libtest.so, liên kết sẽ dừng việc tìm kiếm thư mục Nếu chỉ có một trong hai biến thể hiện hữu ở trong thư mục, thì liên kết sẽ chọn biến thể đó Cách khác, liên kết chọn theo phiên bản thư viện chia sẻ, nếu không bạn phải nhất định chỉ dẫn nó cách khác Bạn có thể sử dụng, -tĩnh tùy chọn cho đòi hỏi lưc trữ tĩnh Ví dụ những dòng sau đây sẽ sử dụng lưu trữ libtest.a, dù là thư viện chia sẻ libtest.so đã sẵn có: % gcc -static -o app app.o -L ltest

Lệnh hiển thị ldd ở thư viện chia sẻ đã liên kết thực hiện được Các thư viện cần sẵn có khi các thao tác lệnh được chạy Chú ý ldd sẽ liệt kê thêm vào các thư viện được gọi là ld-linux.so, nó là một bộ phận của GNU/Linux

Sử dụng LD_LIBRARY_PATH

Khi bạn liên kết một chương trình với một thư viện chia sẻ, liên kết đó không đặt đường dẫn đầy

đủ tới thư viện chia sẻ ở kết mục kết quả thu được Thay vì đó nó chỉ đặt tên ở trong thư viện chia sẻ Khi chương trình thực sự chạy, hệ thống tìm kiếm thư viện chia sẻ và tải nó Hệ thống chỉ tìm kiếm /lib và /usr/lib, theo mặc định Nếu một thư viện chia sẻ được liên kết vào chương trình của bạn và được cài đặt ở bên ngoài thư mục, nó sẽ được tìm thấy, và hệ thống sẽ từ chối chạy chương trình Một giải pháp cho vấn đề đó là sử dụng –Wl,-rpath tùy chọn khi liên kết tới chương trình Cho là bạn có thể sử dụng :

% gcc -o app app.o -L -ltest -Wl,-rpath,/usr/local/lib

Sau đó khi app chạy, hệ thống sẽ tìm kiếm /usr/local/lib cho một vài thư viện phụ thuộc

Một giải pháp khác để giải quyết là đặt môi trường biến số LD_LIBRARRY_PATH khi đang chạy chương trình Như môi trường biến PATH, LD_LIBRARRY_PATH có dấu hai chấm tách rời danh sách của thư mục Ví dụ, nếu LD_LIBRARY_PATH is /usr/local/lib:/opt/lib, then /usr/local/lib and /opt/lib sẽ được tìm kiếm trước thư mục chuẩn /lib and /usr/lib Bạn nên chú ý nếu bạn có LD_LIBRARRY_PATH, liên kết sẽ tìm kiếm thư mục đã định có sự bổ sung thư mục đã định với tùy chọn –L khi nó xây dựng các thao tác có thể thực hiện được

3 Thư viện chuẩn

Tất nhiên nếu như bạn chưa chỉ địn các thư viện khi bạn liên kết nó tới chương trình của bạn, nó

sẽ tất nhiên là sử dụng thư viện chia sẻ Có điều đó bởi vì GCC tự động liên kết tới thư viện C chuẩn.,libc, cho bạn Thư viện C chuẩn không bao gồm các hàm toán học; Thay vào đó chúng ở

Trang 7

trong một thư viện tách rời., libm, bạn cần chỉ định nó một cách rõ ràng Ví dụ biên dịch và liên kết chương trình compute.c nó sử dụng các hàm lượn giác như là sin hay cos, bạn phải dùng code:% gcc -o compute compute.c lm

Nếu bạn viết một chương trình C++ và liên kết nó sử dụng các lệnh trong C++ hoặc g++, bạn sẽcần thư viện C++ chuẩn, libstdc++

4 Thư viện phụ thuộc

Một thư viện sẽ thường phụ thuộc vào một thư viện khác Ví dụ, nhiều GNU/Linux hệ thống baogồm cả libtiff, một thư viện chứa các hàm đọc ra và ghi ảnh files vào trong định dạng TIFF Thư viện đó sẽ quay vòng sử dụng các thư viện libjpeg và libz

Phần listening 2.9 trình bày một chương trình nhỏ có sử dụng libtiff để mở một file ảnh TIFF.Phần listening 2.9 (tifftest.c) sử dụng libtff :

Theo mặc định, nó sẽ thực hiện sự chọn lọc các phiên bản thư viện chia sẻ của libtiff, đã tìm ở /usr/lib/libtiff.so Bởi vì libtiff sử dụng libjpeg và libz, các phiên bản của thư viện chia sẻ của cả hai cũng kéo theo chúng vào(một thư viện chia sẻ có thể trỏ tới một thư viện chia sẻ khác cái mà

nó phụ thuộc Để kiểm chứng điều đó, sử dụng lệnh ldd:

% gcc -static -o tifftest tifftest.c -ltiff

/usr/bin/ /lib/libtiff.a(tif_jpeg.o): In function `TIFFjpeg_error_exit':

tif_jpeg.o(.text+0x2a): undefined reference to `jpeg_abort'

/usr/bin/ /lib/libtiff.a(tif_jpeg.o): In function `TIFFjpeg_create_compress':

tif_jpeg.o(.text+0x8d): undefined reference to `jpeg_std_error'

tif_jpeg.o(.text+0xcf): undefined reference to `jpeg_CreateCompress'

Việc liên kết với một chương trình tĩnh, bạn phải chỉ định tới 2 thư viện riêng của bạn:

% gcc -static -o tifftest tifftest.c -ltiff -ljpeg –lz

Trang 8

Đôi khi, hai thư viện sẽ bị phụ thuộc lẫn nhau qua lại Ở các từ khác, kho trữ đầu tiên sẽ tham chiếu các kí tự được định nghĩa ở trong kho trữ thứ hai Cái hoàn cảnh tổng quát này nảy sinh ra ngoài thiết kế, nhưng nó chỉ đôi khi xảy ra Trong một số trường hợp, bạn có thể quyết định thư viện đơn nhiều thời gian trên các dòng lệnh Kết nối sẽ tìm ra thông tin mới ở mỗi thư viện thời gian mà nó xuất hiện Ví dụ, dòng nguyên nhân libfoo.a tương lai sẽ tìm nhiều khoảng thời gian :

% gcc -o app app.o -lfoo -lbar lfoo

Cho dù là libfoo.a tham chiếu tới các kí tự ở libbar.a, và ngược lại, chương trình sẽ liên kết thànhcông

5 Thuận và chống

Bây giờ bạn cho là đã biết hết mọi thứ về lưu trữ tĩnh và thư viện chia sẻ, bạn chắc chắn sẽ ngạc nhiên với cách sử dụng chúng Có nhiều sự cân nhắc chú ý tới ý định của bạn Một thuận lợi chủ yếu của thư viện chia sẻ là nó lưu trữ được nhiều không gian trên hệ thống nơi mà chương trình được cái đặt Nếu bạn đang cài đặt 10 chương trình, và chúng đều sử dụng chung một thư viện chia sẻ, bạn sẽ giải thoát được nhiều không gian do sử dụng một thư viện chia sẻ Nếu như bạn

sử dụng lưu trữ tĩnh thay vào đó, kho trữ sẽ bao gồm cả 10 chương trình Do đó, sử dụng thư viện chia sẻ đã giải thoát được nhiều không gian đĩa cứng Nó cũng giảm bớt thời gian nếu như chương trình của bạn tải dữ liệu từ Web Lợi thế liên quan tới thư viện chia sẻ là người sử dụng

có thể nâng cấp thư viện không có sự phục thuộc vào chương trình Ví dụ cho là bạn làm ra thư viện chia sẻ quản lí kết nối HTTP Một vài chương trình có thể đã phụ thuộc vào thư viện Nếu như bạn tìm được lỗi ở trên thư viện, bạn có thể nâng cấp hoàn thiện thư viện đó lên Ngay lập tức tất cả chương trình phụ thuộc trên thư viện sẽ được sửa, bạn không cần phải liên kết tất cả các chương trình theo cách mà bạn làm với một kho trữ chuẩn Sự thuận lợi đó khiến bạn nghĩ là bạn nên luôn luôn sử dụng thư viện chia sẻ Tuy nhiên, tại sao lại có sự tồn tại và sử dụng kho trữ Sự thật là việc nâng cấp thư viện chia sẻ ảnh hưởng đến tất cả các chương trình phụ thuộc trên nó nó có thể là một bất lợi Ví dụ, nếu như bạn đang phát triển một phần mềm then chốt, bạn

đã có thể liên kết tới kho trữ tĩnh tuy nhiên nâng cấp thư viện chia sẻ trên hệ thống sẽ không ảnh hưởng tới chương trình của bạn (Cách khác người sử dụng có thể nâng cấp thư viện chia sẻ, bằng cách ngắt chương trình của bạn, và gọi sự hỗ trợ )

Nếu như bạn không thể cài đặt thư viện của bạn ở trong /lib hoặc /usr/lib, bạn nên suy nghĩ chắc chắn trước khi sử dụng thư viện chia sẻ Cá biệt, -Wl, -rpath thủ thuật sẽ không làm việc nếu như bạn không biết nơi mà thư viện sẽ kết thúc Và yêu cầu thông của người sử dụng thiết lập LD_LIBRARY_PATH cách thức thêm bước làm cho chúng Bởi vì mỗi người sử dụng đã phải làm một cách đơn lẻ, đó là công lao lớn lao họ thêm vào Bạn sẽ phải xem sự ảnh hưởng thuận lợi và không thuận lợi cho mọi chương trình mà bạn phân phối

6 Nạp vào động và không nạp

Thỉnh thoảng bạn đã có thể muốn nạp vào một vài code thời gian chạy không dùng liên kết cho code đó Ví dụ , nghĩ tới ứng dụng hỗ trợ modules “plug-in”, như là một trình duyệt web Trình duyệt cho phép bên thứ 3 phát triển tạo ra plug-ins để cung ứng các hàm thêm vào Trình duyệt web sau đó tự động nạp vào code ở các thư viện Các hàm sẵn có sử dụng dưới Linux bởi sử dụng các hàm dlopen Bạn có thể mở một thư viện chia sẻ tên là libtest.so bởi lời gọi dlopen như là:

dlopen ("libtest.so", RTLD_LAZY)

Trang 9

Việc tải sử dụng các hàm, bao gồm <dlfcn.h> ở đầu file và liên kết với tùy chọn ldl một cách tình cờ Sự trả lại các giá trị từ các hàm là một void * đã sử dụng như là một kênh truy cập bộ nhớ ở thư viện chia sẻ.Bạn có thể bỏ qua giá trị tới hàm dlsym tới khi thu được địa chỉ của một hàm cái đã được nạp vào với thư viện chia sẻ Ví dụ, nếu libtest.so định nghĩa một hàm tên là my_function, bạn có thể gọi nó như sau:

void* handle = dlopen ("libtest.so", RTLD_LAZY);

void (*test)() = dlsym (handle, "my_function");

(*test)();

dlclose (handle);

Hệ thống dlsym gọi có thể sử dụng để đạt được con trỏ tới biến số tĩnh ở trong thư viện chia sẻ

Cả dlopen và dlsym trả về NULL nếu như nó không thành công Trong sự việc đó, bạn có thể gọidlerror( không có tham số) để đạt được một thông báo lỗi diễn tả rõ vấn đề đó Hàm dlclose không nạp vào thư viện chia sẻ Kĩ thuật, dlopen nạp thực sự thư viện chỉ có thể khi nó chưa sẵnsàng nạp Nếu thư viện đã vào nạp, dlopen dễ dành tăng một tham chiếu có giá trị Tương tự, dlclose giảm tham chiếu có giá trị và không nạp thư viện chỉ khi tham chiếu có giá trị là zero Nếu như bạn đang viết code ở trên thư viên chia sẻ C++, bạn sẽ chắc chắn muốn trình bày các hàm và các tham số cái mà bạn dự định truy xuất ở một nơi nào đó với ở ngoài liên kết “C” đã chỉ rõ Trong trường hợp đó, nếu hàm trong C++ my_function ở trong một thư viện chia sẻ và bạn muốn truy xuất nó với dlsym, bạn nên trình bày nó như sau:

extern "C" void foo ();

Ngăn cản của trình biên dịch trong C++ là từ việc sai tên hàm, cái sẽ thay đổi tên của hàm là từ foo tới sự khác biệt,các tên được mã hóa thêm thông tin về các hàm Một trình biên dịch sẽ không là hỏng tên; nó sẽ sử dụng bất cứ cái tên nào mà bạn đưa vào thông qua tên hàm và biến số

III Tìm hiểu một chút về shell

Shell là chương trình giữa bạn và Linux (hay nói chính xác hơn là giữa bạn với nhân Linux) Mỗilệnh bạn gõ ra sẽ được Shell diễn dịch rồi chuyển tới nhân Linux Nói một cách dễ hiểu Shell là

bộ diễn dịch ngôn ngữ lệnh, ngoài ra nó còn tận dụng triệt để các trình tiện ích và chương trình ứng dụng có trên hệ thống…

Các loại Shell thông dụng:

Trong thế giới Unix/Linux có rất nhiều Shell…

1) Shell Bourne (sh)

Do Steven Bourne viết, đó là Shell nguyên thuỷ có mặt trên hầu hết các hệ thống Unix/Linux…

Nó rất hữu dụng cho việc lập trình Shell nhưng nó không xử lý tương tác người dung như các Shell khác…

2) Bourne Again Shell (bash)

Đây là phần mở rộng của sh, nó kế thừa những gì sh đã có và phá huy những gì sh chưa có…Nó

có giao diện lập trình rất mạnh và linh hoạt…Cùng với giao diện lệnh dễ dung…Đây là Shell được cài đặt mặc định trên các hệ thống Linux

Trang 10

3) Shell C (csh) Đáp ứng tương thích cho người dung…Nó hỗ trợ rất mạnh cho những

Programmer C…và với đặc tính tự động hoàn thành dòng lệnh…

4) Shell Korn (ksh) Có thể nói đây là một Shell tuyệt vời, nó kết hợp tính năng ưu việt của sh và csh…

Ngoài ra còn có một số Shell khác như: ssh, nfssh, mcsh…

MC (Midnight Commander) một Shell thực hiện yêu cầu của người dung thông qua môi trường

đồ họa…Tương tự như NC (Norton Commander) trong DOS…

IV.Cách biên dịch một chương trình C.

Ngoài vịêc sử dụng IDE biên dịch code C (ví dụ như Dev C, Borland C… ), khác với việc viết một chương trình C trên các hệ điều hành khác như Windows, Linux có tích hợp sẵn công cụ để biên dịch code cho một chương trình C Như vậy, chúng ta có hai cách để biên dịch được một chương trình C, đó là : 1 Sử dụng công cụ có sẵn trong hệ điều hành Linux

2 Sử dụng IDE biên dịch code (Ở đây, chúng ta tìm hiểu về IDE Codeblock)

a) Biên dịch bằng công cụ có sẵn

1.1 Soạn thảo với Emacs

Emacs là trình soạn thảo văn bản đa chức năng Đây là phần mềm tự do, chạy được trên nhiều hệđiều hành và có thể mở rộng để thêm vào chức năng mới Emacs phổ biến trong giới lập trình

máy tính và người dùng máy tính thông thạo kĩ thuật

Chương trình EMACS, tên được tạo ra từ Editor MACroS, đầu tiên dùng cho trình soạn thảo

TECO (Text Editor and Corrector) được Richard Stallman, Guy Steele và Dave Moon viết năm vào 1976 Nó dựa trên cặp chương trình soạn thảo TECO-macro là TECMAC và TMACS được viết bởi Guy Steele, Dave Moon, Richard Greenblatt, Charles Frankston và một số người khác Qua thời gian đã xuất hiện nhiều phiên bản Emacs, nhưng ngày nay 2 phiên bản phổ biến nhất là

GNU Emacs, do Richard Stallman bắt đầu viết vào 1984, và XEmacs, phân nhánh từ GNU Emacs năm 1991 Cả hai đều dùng ngôn ngữ Emacs Lisp có khả năng mở rộng mạnh mẽ, cho phép chúng xử lí nhiều tác vụ khác nhau, từ việc lập trình và biên dịch chương trình máy tính đến duyệt web

Emacs có thể chạy trên nhiều hệ điều hành khác nhau như các hệ thống giống Unix (GNU/Linux,các loại BSD, Solaris, AIX, v.v.), MS-DOS, Microsoft Windows, OpenVMS và Mac OS X.Emacs chạy trên giao diện văn bản lẫn đồ hoạ Trên các hệ điều hành giống Unix, Emacs dùng

hệ thống X Window để tạo giao diện đồ hoạ trực tiếp hoặc thông qua "widget toolkit" như Motif,

Trang 11

LessTif hay GTK+ Emacs có thể dùng giao diện đồ hoạ nguyên thuỷ của Mac OS X và

Microsoft Windows

Một số người phân biệt chữ emacs viết thường, dùng để chỉ các trình biên tập giống Emacs (nhất

là GNU Emacs và XEmacs), và Emacs viết hoa chữ đầu, dùng để chỉ GNU Emacs.

Emacs hiện là một phía của cuộc chiến trình biên tập, phía bên kia là vi

Tính năng:

 Soạn thảo trên nhiều cửa sổ (window) và bộ đệm (buffer)

 Tìm kiếm, thay thế, tự sửa lỗi

Soạn thảo đệ quy (recursive edit): cho phép soạn thảo khi một câu lệnh đang thực hiện

giữa chừng

 Nhiều chế độ soạn thảo: văn bản thường, các file chương trình, ngôn ngữ đánh dấu

(HTML), LaTeX, vẽ hình bằng các kí tự

 Các macro bàn phím

 Sửa đổi theo ý thích cá nhân bằng cách chỉnh sửa các biến của chương trình

 Lập trình bằng ngôn ngữ Emacs Lisp

 Nhiều chương trình phụ trợ (danh sách thư mục, đọc và soạn e-mail, trò chơi )

Một trình biên soạn (editor) là một chương trình mà bạn dùng để soạn thảo mã nguồn Có rất nhiều các trình biên soạn khác nhau có thể dùng được với Linux, nhưng trình biên soạn phổ biến

và được đề cao nhất đương nhiên là GNU Emacs

1.1.1 Mở một file nguồn C hoặc C++

Bạn có thể khởi động Emacs bằng cách gõ emacs trong cửa sổ lệnh và nhấn nút Return Khi Emacs đã được khởi động, bạn có thể sử dụng các ký hiệu phía trên để tạo một file mới Bấm vào menu Files, chọn Open Files, rồi sau đó gõ tên file mà bạn muốn mở vào ô “minibuffer” ở phía dưới cùng mành hình Nếu bạn muốn tạo một file nguồn C, bạn kết thúc tên file bằng c hoặc h Nếu bạn muốn tạo một file nguồn C++, bạn kết thúc tên file bằng

.cpp, hpp, cxx, hxx, C hoặc H Khi file đã được mở ra, bạn có thể soạn thảo như mong muốn bằng bất kỳ chương trình soạn thảo văn bản thông thường nào Để lưu file, chọn Save Buffer trong menu Files Khi bạn đã kết thúc sử dụng Emacs, bạn có thể chọn Exit Emacs trong menu Files

Nếu bạn không thích trỏ và bấm, bạn có thể sử dụng các phím tắt để tự động mở, lưu file và thoátEmacs Để mở một file, bấm tổ hợp phím Ctrl+X rồi Ctrl+F Để lưu một file, bấm Ctrl+X rồi Ctrl+S Để thoát Emacs, bấm Ctrl+X rồi Ctrl+C Nếu bạn muốn làm quen hơn với Emacs, bạn nên chọn mục Emacs Tutorial trong Help menu Tutorial cung cấp cho bạn rất nhiều hướng dẫn

để bạn sử dụng Emacs một cách hiệu quả

1.1.2 Tự động định dạng

Nếu bạn đã quen với việc lập trình trong môi trường phát triển hợp nhất (Integrated

Development Environment - IDE), bạn cũng sẽ quen với việc trình biên soạn giúp bạn định dạng đoạn mã của mình Emacs có thể cung cấp kiểu chức năng tương tự như vậy Nếu bạn mở một

Ngày đăng: 13/03/2023, 08:03

TỪ KHÓA LIÊN QUAN

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

w