lập trình c và shell trên linux

57
Môn hc: Lp trình hthng Phn: Hđiu hành Linux Trang 1 Báo Cáo LẬP TRÌNH HỆ THỐNG Đề Tài: Hệ điều hành Linux GVGD: Phạm Văn Khoa SVTH: Đinh Văn Mạnh 09119059 Lương Văng Giang 09119010 Trần Minh Thanh 09119034 Đặng Quang Thịnh 09119039

Upload: jciver-jponest

Post on 07-Aug-2015

487 views

Category:

Documents


3 download

DESCRIPTION

PHẦN I. LẬP TRÌNH SHELLI. Bash shellII. Ngôn ngữ C shellIII. Trình bày sự khác nhau trong cấu trúc điều khiển giữa 2 loại shell nàyPHẦN II. LẬP TRÌNH C TRÊN LINUXA. Thư viện liên kết trên LinuxB. Makefile: sử dụng trong biên dịch mã nguồn

TRANSCRIPT

Page 1: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 1

Báo Cáo

LẬP TRÌNH HỆ THỐNG

Đề Tài: Hệ điều hành Linux

GVGD: Phạm Văn Khoa

SVTH: Đinh Văn Mạnh 09119059

Lương Văng Giang 09119010

Trần Minh Thanh 09119034

Đặng Quang Thịnh 09119039

Page 2: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 2

Mục lục

PHẦN I. LẬP TRÌNH SHELL .......................................................................................... 4

I. Bash shell ................................................................................................................ 4

1. Sử dụng biến ........................................................................................................ 4

2. Cấu trúc điều khiển ........................................................................................... 10

3. Danh sách AND (&&) ......................................................................................... 16

4. Danh sách Or ....................................................................................................... 18

5. Tài liệu here ......................................................................................................... 18

II. Ngôn ngữ C shell ..................................................................................................... 19

1. Biến ..................................................................................................................... 19

2. Cấu trúc điều kiện If .......................................................................................... 20

3. Câu lệnh while: .................................................................................................. 20

4. Nhiều điều kiện - AND/OR ................................................................................ 21

5. Câu lệnh foreach:............................................................................................... 21

6. Câu lệnh while: .................................................................................................. 22

7. Switch … case ................................................................................................... 22

8. Tham số dòng lệnh: .......................................................................................... 23

III. Trình bày sự khác nhau trong cấu trúc điều khiển giữa 2 loại shell này ............ 23

1. Mệnh đề If .......................................................................................................... 23

2. Dạng If … else .................................................................................................... 24

3. Dạng else - if ....................................................................................................... 24

4. Mệnh đề case ...................................................................................................... 25

5. Mệnh đề for ........................................................................................................ 26

6. Mệnh đề while .................................................................................................... 26

7. Mệnh đề Until .................................................................................................... 27

PHẦN II. LẬP TRÌNH C TRÊN LINUX ....................................................................... 34

A. Thư viện liên kết trên Linux ................................................................................ 34

a. Thư viện liên kết tĩnh......................................................................................... 34

b. Thư viện liên kết động ....................................................................................... 42

B. Makefile: sử dụng trong biên dịch mã nguồn. .................................................... 50

1. Vì sao ta phải dùng Makefile? ........................................................................... 50

Page 3: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 3

2. ........................................................ 53

3. Ví dụ Demo sử dụng Makefile ........................................................................... 55

Page 4: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 4

PHẦN I. LẬP TRÌNH SHELL

Các shell trên unix/linux - Sh ( Bourne) : shell nguyên thủy áp dụng cho Unix

- Csh, Tcsh, zsh : Dòng shell sử dụng cấu trúc lệnh của C làm ngôn ngữ kịch

bản. Được tạo ra đầu tiên bởi Bia Joy. Là Shell thông dụng thứ hai sau Bash

Shell.

- Bash : shell chủ yếu của Linux. Ra đời từ dự án GNU.bash (viết tắt của

Bourne Again Shell ) có lợi điểm là mã nguồn được công bố rộng rãi. Các bạn

có thể tải về và sử dụng miễn phí tại www.gnu.org

- Rc : Shell mở rộng của csh với nhiều tương thích với ngôn ngữ C hơn. Rc

cũng ra đời từ dự án GNU

Chú ý : Tuy bash là shell là shell chuẩn được các nhà phân phối sử dụng phổ biến

trong Linux nhưng các ví dụ về lập trình sẽ sử dụng ngôn ngữ và lệnh của shell sh

bởi vì shlà shell nguyên thủy, có thể chạy trên cả Unix. Bằng lệnh file ta sẽ thấy

trong hầu hết các bản Linux hiện nay sh chỉ là liên kết dẫn đến bash mà thôi.

Ví dụ : $file / bin / sh

/bin/sh : symbolic link to bash

Điều này có nghĩa là bash hoàn toàn có thể diễn dịch và điều khiển các lệnh của shell

sh.

I. Bash shell

Ở phần này ta sẽ tìm hiểu về :

- Biến: kiểu chuỗi, kiểu số, tham số và biến môi trường.

- Điều kiện : kiểm tra luận lý Boolean bằng shell

- Điều kiện chương trình: if, elif, for, while, until, case

1. Sử dụng biến

- Thường thì ta không cần phải khai báo biến trước khi sử dụng. Thay vào đó

biến sẽ tự động tạo và khai báo khi lần đầu tiên tên biến xuất hiện, chằng hạn

như trong phép gán. Mặc định tất cả các biến đều được khởi tạo và mang trị

kiểu string.Tương tự như HĐH và ngôn ngữ C, cú pháp Shell phân biệt chữ

hoa chữ thường, biến mang tên foo, Foo, FOO là 3 biến khác nhau.

- Bên trong Script của Shell, bạn có thể lấy về nội dung của biến bằng cách

dùng dấu $ đặt trước tên biến. Để hiển thị nội dung của biến, bạn có thể dùng

Page 5: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 5

lệnh echo. Khi gán nội dung cho biến bạn không cần sử dụng ký tự $ . Ví dụ

trên dòng lệnh, bạn có thể gán nội dung và hiển thị biến như sau :

$ xinchao = hello

$echo $xinchao

Hello

$ xinchao = “I am here”

$echo $xinchao

I am here

$ xinchao =12+1

$echo $xinchao

12+1

Lưu ý : sau dấu = không được có khoảng trắng. Nếu gán nội dung chuỗi có khoảng

trắng cho biến, cần bao bọc chuỗi bằng dấu “ “.

1.1 Các ký tự đặc biệt

1.1.1 Các ký tự chuyển hướng vào/ ra

Ký hiệu Ý nghĩa

> Đầu ra hướng tới

>> Nối vào nội dung của

< Lấy đầu vào từ <

<< Đầu vào là ở đây

2> Đầu ra báo lỗi sẽ hướng vào

2>> Đầu ra báo lỗi hướng và ghi thêm vào

1.1.2 Các ký tự kiểm soát tiến trình

• Dấu & ( ampersand) : đặt một tiến trình vào chế độ chạy nền. Với & chương

trình sẽ tự chạy và shell quay ngay về tương tác với người dùng, trả lại dấu nhắc

ngay. Tiến trình nền có nhiều cách để kiểm soát.

• Dấu ( ; ) Dùng để nhóm một số lệnh lại, phân cách bởi ;

• Dấu ` ` (backqoutes) Dấu thay thế.

Bất kỳ lệnh nào xuất hiện trong dấu nháy sẽ được thực hiện trước và kết quả của

lệnh đó sẽ thay thế đầu ra chuẩn (stdout) trước khi lệnh trong dòng lệnh thực hiện

• Pipeline

Page 6: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 6

Shell cho phép kết quả thực thi một lệnh, kết hợp trực tiếp đầu vào của lệnh khác mà

không cần xử lý trung gian

cmd & Đặt lệnh cmd chạy nền

cmd1 ; cmd2 Chạy cmd1 trước sau đó chạy cmd2

(cmd) Thực hiện cmd trong một shell con

`cmd` Đầu ra cmd sẽ thay cho đầu ra của lệnh trong dòng lệnh

Cmd1\cmd2 Nối đầu ra của cmd1 vào đầu vào của cmd2

• Dấu “ ” hay „ ‟

Ví dụ dấu “” hoặc „ ‟

#!/bin/bash

myvar="Hi there"

echo $myvar

echo "message : $myvar"

echo 'message : $myvar'

echo "message :\$myvar"

echo Enter some text

read myvar

echo '$myvar' now equals $myvar

exit 0

Kết xuất khi thực thi script :

Hi there

Message : Hi there

Message: $myvar

Message: $myvar

Enter some text

Hello world

$myvar now equals Hello World

Page 7: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 7

Cách chương trình làm việc: Biến myvar được tạo ra và khởi gán giá trị

chuỗi Hi there. Nội dung của biến sau đó được hiển thị bằng lệnh echo trong các trường

hợp bọc chuỗi bằng dấu nháy kép, nháy đơn và dấu hiển thị đắc biệt . Tóm lại nếu muốn

thay thế nội dung biến trong một chuỗi cần bọc chuỗi bằng nháy kép. Nếu muốn hiển

thị toàn bộ nội dung của chuỗi,hãy dùng nháy đơn.

1.2 Biến môi trường

Khi trình shell khởi động nó cung cấp sẵn một số biến được khai báo và gán

giá trị mặc định. Chúng được gọi là các biến môi trường. Các biến này thường được

viết hoa để phân biệt với các biến do người dùng tự định nghĩa ( thường là ký tự

không hoa ). Nội dung các biến này thường tùy vào thiết lập của hệ thống sử dụng.

Danh shell của các biến môi trường là khá nhiều, nhưng nhìn chung nên nhớ một số

biến môi trường chủ yếu sau:

Biến môi trường Ý nghĩa

$HOME Chứa nội dung của thư mục chủ

$PATH Chứa danh shell các đường dẫn

$PS1 Dấu nhắc hiển thị trên dòng lệnh. Thường là $user

$SP2 Dấu nhắc thứ cấp, thông báo người dùng nhập thêm thông tin trước khi

lệnh thực hiện. Thường là dấu >

$IFS Dấu phân cách các trường hợp trong danh shell chuỗi

$0 Chứa tên chương trình gọi trên dòng lệnh

$# Số tham số truyền trên dòng lệnh

$$ Mã tiến trình của shell script thực thi

Mỗi môi trường mà user đăng nhập chứa một số danh shell biến môi trường dùng

cho mục đích riêng. Có thể dùng lệnh export của shell .

1.3 Biến tham số (parameter variable)

- Nếu cần tiếp nhận tham số trên dòng lệnh để xử lý, có thể dùng thêm các biến

môi trường sau:

Biến tham số Ý nghĩa

$1,$2,$3 Vị trí và nội dung của các tham số trên dòng lệnh theo thứ

tự trái – phải

Page 8: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 8

S* Danh shell của tất cả các tham số trên dòng lệnh. Chúng

được lưu trong một chuỗi duy nhất phân cách bằng ký tự

đầu tiên quy định trong biến $IFS

S@ Danh shell các tham số được chuyển thành chuỗi. Không

sử dụng dấu phân cách của biến IFS

Ví dụ sau sẽ minh họa một số cách đơn giản xử lý và truy xuất biến môi

trường .

- Ví dụ: Try_var.sh

#!/bin/bash

salutation="Hello"

echo $salutation

echo "The program $0 is now running"

echo "The second parameter was $2"

echo "The first parameter was $1"

echo "The parameter list was $*"

echo "The user's home directory is $HOME"

echo "Please enter a new greeting"

read salutation

echo $salutation

echo "The script is now complete"

exit 0

Lưu tên tập là try_var.sh, đổi thuộc tính thực thi x cho tập tin bằng lệnh :

$chmod+x try_var.sh

Khi chạy try_varsh từ dòng lệnh,bạn sẽ nhận được kết quả của kết xuất như

sau :

$./try_var.sh foo bar baz

Hello

The program./try_var.sh is now running

The second parameter was bar

Page 9: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 9

The first parameter was foo

The parameter list was foo bar baz

The user‟s home directory is/home/xyz

Please enter a new greeting

Xin chao!

Xin chao!

The script is now complete

Ví dụ dấu “” hoặc „ ‟

#!/bin/bash

myvar="Hi there"

echo $myvar

echo "message : $myvar"

echo 'message : $myvar'

echo "message :\$myvar"

echo Enter some text

read myvar

echo '$myvar' now equals $myvar

exit 0

Kết xuất khi thực thi script :

Hi there

Message : Hi there

Message: $myvar

Message: $myvar

Enter some text

Hello world

$myvar now equals Hello World

Cách chương trình làm việc: Biến myvar được tạo ra và khởi gán giá trị

chuỗi Hi there. Nội dung của biến sau đó được hiển thị bằng lệnh echo trong

Page 10: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 10

các trường hợp bọc chuỗi bằng dấu nháy kép, nháy đơn và dấu hiển thị đắc

biệt \. Tóm lại nếu muốn thay thế nội dung biến trong một chuỗi cần bọc chuỗi

bằng nháy kép. Nếu muốn hiển thị toàn bộ nội dung của chuỗi,hãy dùng nháy

đơn.

2. Cấu trúc điều khiển

2.1. Lệnh if

- Lệnh If tuy đơn giản nhưng được sử dụng nhiều nhất . If kiểm tra điều kiện

đúng hoặc sai để thực thi biểu thức thích hợp.

If condition

Then

Statements

Else

Statements

Ví dụ : Đoạn script sau sử dụng if tùy vào câu trả lời của bạn mà đưa ra lời chào

thích hợp : if_control.sh

#!/bin/bash

Echo” Is it morning? Please answer yes or no”

Read timeofday

If [$timeofday = “yes” ]; then

Echo” Good morning”

Else

Echo “ Good afternoon”

Fi

Exit 0

Kết quả của scrift

$./If_control.sh

Is it morning? Please answer yes or no

Yes

Good morning

$

2.2. Lệnh Elif

Page 11: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 11

- Trong ví dụ If_control.sh ở trên có rất nhiều phát sinh. Tất cả các câu trả lời

khác với “yes” đều có nghĩa là “no”. Chúng ta có thể khắc phục điều này bằng

cách sử dụng cấu trúc điều khiển elif. Mệnh đề này cho phép kiểm tra điều

kiện lần thứ 2 bên trong else. Script dưới đây có thể hoàn chỉnh hơn, có thể in

ra thông báo lỗi nếu người dùng nhập không đúng “yes” hoặc “no”

Ví dụ: Elif_control.sh

#!/bin/bash

Echo “Is it morning? Please answer yes or no”

Read timeofday

If [$timeofday = ”yes”]; then

Echo”good morning”

Elif[$timeofday= “no”]; then

Echo” Good afternoon”

Else

Echo “ Sorry, $timeofday not recognized. Enter yes or no”

Fi

Exit 0

Chú ý : Tương tự như ví dụ if_control.sh nhưng ta sử dụng them elif để kiểm

tra trường hợp người dùng không nhập “no”. Thông báo lỗi được in ra và mã

lỗi trả về bằng lệnh exit là 1. Trường hợp hoặc “yes” hoặc “no” được nhập

vào, mã lỗi trả về sẽ là 0.

2.3. Lệnh For

- Sử dụng for để lặp lại một số lần với các giá trị xác định. Phạm vi lặp có thể

nằm trong một tập hợp chuỗi chỉ định tường minh bởi chương trình hay là kết

quả trả về từ một biến hoặc biểu thức khác.

Cú pháp:

For variable in values

Do

Statements

Page 12: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 12

Done

Ví dụ: for.sh

#!/bin/bash

rm -rf fred*

echo > fred1

echo > fred2

mkdir fred3

echo > fred4

for file in fred*

do

if [ -d "$file" ]; then

break;

fi

done

echo first directory fred was $file

exit 0

2.4. Lệnh Case

- Lệnh Case có cách sử dụng hơi phức tạp hơn các lệnh đã học. Cú pháp của

lệnh case như sau :

Case variable in

Pattern[ | partten]….) statement ; ;

Pattern[ | partten]….) statement ; ;

….

Esac

- Mặc dù nhìn khá khó hiểu , nhưng lệnh case rất linh động. Case cho phép thực

hiện so khớp nội dung của biến với một chuỗi mẫu pattern nào đó. Khi một

mẫu được so khớp thì lệnh statement tương ứng sẽ được thực hiện. Hãy lưu ý

đặt dấu ;; phía sau mỗi mệnh đề so khớp pattern, shell dùng dấu hiệu này để

nhận dạng mẫu pattern so khớp tiếp theo mà biến cần thực hiện.

Page 13: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 13

- Việc cho phép so khớp nhiều mẫu khác nhau làm case trở nên thích hợp cho

việc kiểm tra nhập liệu của người dùng.

Sau đây là ví dụ : case1.sh

#!/bin/bash

echo "Is it morning? Please answer yes or no"

read timeofday

case "$timeofday" in

"yes") echo "Good Morning";;

"no" ) echo "Good Afternoon";;

"y" ) echo "Good Morning";;

"n" ) echo "Good Afternoon";;

* ) echo "Sorry, answer not recognised";;

esac

exit 0

- Cách thực hiện: Sauk hi người dùng nhập vào câu trả lời, lệnh case sẽ lấy nội

dung của biến $timeofday so sánh với từng chuỗi. Khi gặp chuỗi thích hợp nó

sẽ thực thi lệnh sau dấu ) và kết thúc (không tiếp tục so khớp với các mẫu

khác) . Ký tự đại diện * cho phép so khớp với mọi loại chuỗi. * thường được

xem như trường hợp so sánh đúng cuối cùng nếu các mẫu so sánh trước đó

thất bại. Bạn có thể xem * là mệnh đề default trong lệnh switch của C hay

case….else của Pascal.

- Ngoài cách trên, ta có thể kết hợp chung các mẫu so khớp với nhau khiến cho

case ngắn gọn hơn như sau: case2.sh

#!/bin/bash

echo "Is it morning? Please answer yes or no"

read timeofday

case "$timeofday" in

"yes" | "y" | "Yes" | "YES" ) echo "Good Morning";;

"n*" | "N*" ) echo "Good Afternoon";;

* ) echo "Sorry, answer not recognised";;

esac

Page 14: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 14

exit 0

Script trên sử dụng nhiều mẫu so khớp trên một dòng so sánh của lệnh case . Các

mẫu này có ý nghĩa tương tự nhau và yêu cầu thực thi cùng một lệnh nếu điều kiện

đúng xảy ra. Cách viết này thực tế thường dùng và dễ đọc hơn cách viết thứ nhất.

Mặc dù vậy. hãy tìm hiểu case ở ví dụ sau, case sử dụng lệnh exit để trả về mã lỗi

cho từng trường hợp so sánh mẫu đồng thời case sử dụng cách so sánh tắt bằng ký tự

đại diện.

Ví dụ: Case3.sh

#!/bin/bash

echo "Is it morning? Please answer yes or no"

read timeofday

case "$timeofday" in

"yes" | "y" | "Yes" | "YES" )

echo "Good Morning"

echo "Up bright and early this morning?"

;;

"[nN]*" )

echo "Good Afternoon"

;;

* )

echo "Sorry, answer not recognised"

echo "Please answer yes or no"

exit 1

;;

esac

exit 0

- Cách thực hiện : Trong trường hợp “no” ta dùng ký tự đại diện * thay thế cho

tất cả ký tự n và N. Điều này có nghĩa là nx hay Nu…đều có nghĩa là „no‟. Ở

ví dụ trên ta đã thấy cách đặt nhiều lệnh trong cùng một trường hợp so khớp .

Exit 1 cho biết người dùng không chọn yes và no. Exit 0 biết người dùng đã

chọn yes , no theo yêu cầu:

Có thể không cần đặt ;; ở mẫu so khớp cuối cùng trong

Page 15: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 15

lệnh case (phía trước esac) , vì không còn mẫu so khớp nào cần thực hiện nữa.

Không như C yêu cầu phải đặt lệnh break ở mỗi mệnh đề case, shell không đòi hỏi

điều này, nó biết tự động chấm dứt khi lệnh case tương ứng đã tìm được mẫu thỏa

mãn.

- Để làm case trở nên mạnh mẽ và so sánh được nhiều trường hợp hơn, có thể

giới hạn các ký tự so sánh theo cách sau : [yy] | [Yy] [Ee] [Ss] , khi đó y, Y

hay yes, YES…đều được xem là yes. Cách này đúng hơn là dùng ký tự thay

thế toàn bộ * trong trường hợp [nN]*.

2.5 Lệnh while

Lệnh while cho phép thực hiện lặp vô hạn khi điều kiện kiểm tra vẫn còn đúng

Cú pháp:

While condition do

Statements

Done

Ví dụ : password.sh

#!/bin/sh

Echo “enter password”

Read trythis

While [“$trythis” !- “secret”]; do

Echo “ sorry, try again”

Ready trythis

Done

Exit 0

Kết xuất của script

$./password.sh

Enter password

Abc

Sorry, try again

Secret

$

Page 16: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 16

Lệnh while liên tục kiểm tra nội dung biến $trythis , yêu cầu nhập lại

dữ liệu bằng lệnh read một khi $trythis vẫn chưa bằng với chuỗi “secret”.

2.6. Lệnh until

Cú pháp lệnh:

Until condition

Do

Statements

Done

Lệnh until tương tự lệnh while nhưng điều kiện kiểm tra bị đảo ngược lại.

Vòng lặp sẽ bị dừng nếu điều kiện kiểm tra là đúng.

Ví dụ sau sử dụng lệnh until để chờ user đăng nhập

Ví dụ until_user.sh

#!/bin/sh

Echo “Locate for user…”

Until who | grep “$1” > dev/null

Do

Sleep 60

Done

Echo –e\\a

Echo “***** $1 has just logged in ******”

Exit 0

Lệnh who đọc danh shell các user đăng nhập vào hệ thống, chuyển

danh shell này cho grep bằng cơ chế đường ống ( | ) . Lệnh grep lọc ra tên user

theo biến môi trường $1 hiện có nội dung là chuỗi xyz. Một khi lệnh grep lọc

ra dữ liệu , nó sẽ truyền ra vùng tập tin rỗng/dev/null và trả lại giá trị null,

lệnh until kết thúc.

3. Danh sách AND (&&)

Page 17: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 17

- Danh shell AND cho phép thực thi một chuỗi cạnh kề nhau, lệnh sau chỉ thực

hiện khi lệnh trước đã thực thi và trả về mã lỗi thành công. Cú pháp sử dụng

như sau : Statement1 && statement2 && statement3 &&….

- Bắt đầu từ bên trái statement1 sẽ thực hiện trước, nếu trả về true thì

statement2 tiếp tục được gọi. Nếu statement2 trả về false thì shell chấm dứt

danh shell AND và ngược lại statement3 sẽ được gọi ….Toán tử && dùng

để kiểm tra kết quả trả về của statement trước đó. Kết quả trả về của AND sẽ

là true nếu tất cả các lệnh statement đều được gọi thực thi. Ngược lại là false.

- Ví dụ sau dùng lệnh toauch file_one (để kiểm tra file_one tồn tại hay chưa,

nếu chưa thì tạo mới) tiếp đến rm file_two. Sau cùng danh shell AND sẽ kiểm

tra xem các file có đồng thời tồn tại hay không để đưa ra thông báo thích hợp.

Ví dụ and.sh

#!/bin/bash

touch file_one

rm -f file_two

if [ -f file_one ] && echo "hello" && [ -f file_two ] && echo "there"

then

echo -e "in if"

else

echo -e "in else"

fi

exit 0

Chạy thử script trên bạn sẽ nhận được kết quả như sau :

$./and_list.sh

Hello

In else

- Cách chương trình làm việc : Lệnh touch và rm đảm bảo rằng file_one tồn tại

và file_two không có. Trong danh shell biểu thức if, && sẽ gọi lệnh [-f

file_one ] trước. Lệnh này thành công vì touch đã tạo sẵn file_one. Lệnh echo

tiếp tục được gọi luôn trả về trị true nên theo lệnh tiếp theo [-f file_two] thi

hành. Do file_two không tồn tại nên echo “there” không được gọi. Toàn bộ

Page 18: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 18

biểu thức trả về giá trị false (vì các lệnh trong danh shell không được thực thi

hết). Do if nhận trị false nên echo trong mệnh đề else của lệnh if được gọi.

4. Danh sách Or

Danh sách OR cũng tương tự với AND là thực thi một dãy các lệnh trả về true

thì việc thực thi dừng lại. Cú pháp như sau :

Statement1||statement2||statement3 &&….

Ví dụ: or_list.sh

#!/bin/sh

Rm –f file_one

If [ -f file_one] || echo “hello” || echo “there”

Then

Echo “ in if”

Else

Echo “ in else”

Fi

Exit 0

Cách chương trình làm việc: File_one đầu tiên được loại bỏ để đảm

bảo lệnh if tiếp theo không tìm thấy nó. Lệnh [-f file_one ] trả về false vì

file_one không tồn tại. Lệnh echo tiếp theo trong chuỗi danh shell OR sẽ được

gọi in ra hello. Do echo luôn trả về true nên echo tiếp theo không được gọi.

Bởi vì trong danh shell OR có một lệnh trả về true nên toàn bộ biểu thức sẽ là

true. Kết quả cuối cùng là echo trong if được gọi để in ra chuỗi “in if”.

5. Tài liệu here

- Unix và Linux cung cấp cơ chế tự động hóa mô phỏng việc nhập hõ vào từ

bàn phím bằng tài liệu here ( here document). Ta để sẵn các phím hay chuỗi

cần gõ trong một tập tin và chuyển hướng tập tin này cho lệnh cần thực thi.

Nó sẽ tiếp nhận và đọc nội dung tập tin như những gì đã gõ từ bàn phím.

- Ví dụ, khi gõ lệnh cat , nó sẽ chờ nhập dữ liệu gõ vào từ bàn phím. Nếu khi

script thực thi không có mặt người dùng ở đó thì sao? Quá trình tự động của

Page 19: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 19

script sẽ dừng lại chờ đến khi ta xuất hiện để gõ dữ liệu vào. Cơ chế tài liệu

here giúp thực hiện tự động nhập liệu như sau : ví dụ cat_here

#! /bin/bash

cat > test.txt <<!YOURLABEL!

Hello

This is

here document

!YOURLABEL!

Kết quả khi thực thi cat_here.sh, tệp test.txt được tạo ra. Với nội dung là chuỗi Hello

This is…ta không cần phải dùng tay nhập dữ liệu cho lệnh cat.

Tài liệu here yêu cầu đặt cú pháp ở giữa nhãn bắt đầu và nhãn kết thúc. Trong ví dụ

trên nhãn bắt đầu là !YOURLABEL! ( Lưu ý đến ký tự << ở đầu dùng để cho biết

nơi bắt đầu của tài liệu here) ,nhãn kết thúc là !YOURLABEL! . Dấu ! hai bên nhãn

YOURLABEL chỉ để dễ dàng nhận ra nhãn mà thôi, trong trường hợp nội dung dữ

liệu của chuỗi YOURLABEL thì cặp ! ! cũng dùng để phân biệt riêng tên nhãn của

người dùng.

II. Ngôn ngữ C shell

Cấu trúc C Shell: C Shell cung cấp ngôn ngữ dòng lệnh tương tự như ngôn ngữ lập trình

C. Ngôn ngữ C shell chứa cấu trúc: nhập và xuất, toán tử điều kiện, quản lý tập tin và

định nghĩa biến...Nếu bạn đã làm quen với các ngôn ngữ lập trình cấp thấp, thì lập trình

shell sẽ rất đơn giản.

1. Biến

Lệnh cơ bản để khai báo biến trong C shell là set. Ví dụ:

set name = "Henri"

=> sẽ khởi tạo biến name chứa giá trị "Henri".

set users = (George Frank Mary Heloise Hartsell)

=> sẽ khởi tạo biến có kiểu dữ liệu wordlist (mảng chuỗi), bây giờ chúng ta có thể truy

cập giá trị này bằng index của chúng.

@ count = 0

=> khởi tạo biến kiểu integer.

Page 20: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 20

Ghi chú: lệnh set chỉ được sử dụng cho các biến shell. Biến môi trường như DISPLAY,

EDITOR...phải được khai báo bằng lệnh setenv.

2. Cấu trúc điều kiện If

a. If...then

Cho phép người dùng thực thi một lệnh hoặc một nhóm lệnh chỉ khi điều kiện phù hợp.

Cấu trúc như sau:

if (condition(s))

then

command(s)

endif

Điều kiện trong dấu ngoặc được tính trước và trả về giá trị 0 (false) hoặc 1 (true). Chỉ

khi điều kiện là true các lệnh mới được thực thi.

b. If...then...else

Cấu trúc này cho phép người dùng xác định nhóm lệnh "default" - thực thi nếu điều kiện

sau từ khóa if là false, ngược lại nhóm lệnh giữa điều kiện if và từ khóa else sẽ thực thi.

if (condition(s))

then

command group 1

else

command group 2

end if

3. Câu lệnh while:

Có lúc bạn cần thực thi một lệnh lặp đi lặp lại cho đến khi điều kiện phù hợp. Nếu cấu

trúc if...then không đáp ứng được, bởi vì điều kiện của nó chỉ được tính toán một lần.

Đặt điều kiện trong foreach cũng không đáp ứng được hoặc khó coi, bởi vì số vòng lặp

vô hạn. Chúng ta cần một vòng lặp xoay vòng không hạn định cho đến khi giá trị của

điều kiện là false. Trong trường hợp này, chúng ta sử dụng câu lệnh while:

while (condition)

statements

end

Page 21: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 21

4. Nhiều điều kiện - AND/OR

- Toán tử AND là && - điều kiện ghép là true nếu cả tất cả điều kiện là true.

- Toán tử OR là || và điều kiện ghép sẽ là true nếu một trong tất cả điều kiện là true.

Toán tử kiểm tra tập tin:

operator filename

Ví dụ:

Chạy lệnh dựa vào điều kiện tập tin "mail.log" có tồn tại hay không.

if (-e mail.log) then

cat new.log >> mail.log

endif

Sử dụng biến thay thế cho tên tập tin:

set file_to_remove = .pine-interrupted-mail

if (-z $file_to_remove) then

rm $file_to_remove

endif

=> kiểm tra file có tên chứa trong biến có chiều dài là 0 hay không, nếu đúng là xóa file

đó đi.

Toán tử Ý nghĩa

-d tập tin là thư mục?

-e tập tin tồn tại?

-f plain file?

-o quyền chủ sở hữu?

-r quyền đọc?

-w quyền ghi?

-x quyền thực thi?

-z tập tin có chiều dài là 0?

Để đảo ngược giá trị của toán tử này, sử dụng ! trước toán tử trong dấu ngoặc (ví dụ như

! -z filename).

5. Câu lệnh foreach:

Page 22: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 22

Câu lệnh foreach cho phép bạn thực thi một lệnh hoặc một nhóm lệnh cho mỗi file mà

tên của nó phù hợp với mẫu xác định. Ví dụ: tạo script xóa file rỗng và file có tên là core

trong thư mục home của bạn.

#!/bin/csh

foreach dudfile(/home/users1/hansel/*)

if (-z $dudfile || $dudfile == "core") then

rm $dudfile

endif

end

6. Câu lệnh while:

Có lúc bạn cần thực thi một lệnh lặp đi lặp lại cho đến khi điều kiện phù hợp. Nếu cấu

trúc if...then không đáp ứng được, bởi vì điều kiện của nó chỉ được tính toán một lần.

Đặt điều kiện trong foreach cũng không đáp ứng được hoặc khó coi, bởi vì số vòng lặp

vô hạn. Chúng ta cần một vòng lặp xoay vòng không hạn định cho đến khi giá trị của

điều kiện là false. Trong trường hợp này, chúng ta sử dụng câu lệnh while:

while (condition)

statements

end

7. Switch … case

Chọn lựa từ danh sách:

Giả sử bạn viết một chương trình menu. Người dùng chọn số từ 1 đến 6. Một hành động

sẽ được thực hiện phụ thuộc vào những gì người dùng chọn. Chúng ta có thể sử dụng

một chuỗi câu lệnh if...then...else if...then...else if...then..., nhưng rất khó coi và khó đọc

nếu chúng ta debug chương trình. Thay vào đó chúng ta có thể sử dụng chức năng

switch...case.

#!/bin/csh

echo -n "Please enter your first name: "

set uname = $<

switch ($uname)

case [Gg]eorge:

Page 23: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 23

cat /messages/George

breaksw

case [Mm]ary:

cat /messages/Mary

breaksw

case [Ss]andy:

cat /messages/Sandy

breaksw

default:

cat /messages/Goodbye

exit 1

endsw

8. Tham số dòng lệnh:

Nếu bạn muốn script của bạn chạy giống như các lệnh UNIX khác - cho phép người

dùng chuyển vào tên tập tin hoặc chuỗi, thì bạn sẽ cần sử dụng khả năng tham số của C

shell. Trong C shell có biến đặc biệt là argv. Biến này có kiểu dữ liệu wordlist, mỗi từ

trên dòng lệnh là một phần tử trong mảng. Ví dụ chúng ta đã viết script wrap cho phép

thực hiện một số chức năng trên file, chúng ta gọi script với cấu trúc:

wrap infile outfile

Trong script này giá trị argv[1] sẽ là infile và giá trị argv[2] sẽ là outfile. Chúng ta có thể

truy cập các giá trị này như sau:

#!/bin/csh

if (!-e $argv[1]) then

echo "Error: file $argv[1] does not exist."

exit 2

endif

III. Trình bày sự khác nhau trong cấu trúc điều khiển giữa

2 loại shell này

Cấu trúc điều khiển gồm If, Elif , For, While, Until, Case

1. Mệnh đề If

Page 24: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 24

bash csh

if [bieu_thuc]

then

cau_lenh

...

fi

if (bieu_thuc)

then

cau_lenh

...

endif Nếu biểu thức bieu_thuc được đánh giá là Đúng thì (các) câu lệnh cau_lenh sẽ được

thực hiện, còn không thì chương trình sẽ bỏ qua và thực hiện ngay câu lệnh phía sau fi

hoặc endif.

Nếu chỉ có một câu lệnh được thực hiện trong if thì Csh còn có một dạng đơn giản hơn

là :

if (bieu_thuc) cau_lenh

2. Dạng If … else

bash Csh

if [bieu_thuc]

then

cau_lenh

...

else

cau_lenh

...

fi

if (bieu_thuc) then

cau_lenh

...

else

cau_lenh

...

endif

Dạng này mở rộng dạng đơn giản nói trên ở chỗ: nếu bieu_thuc là Sai thì (các)

câu lệnh cau_lenh sau else sẽ được thực hiện.

3. Dạng else - if

Nếu sau else còn tiến hành kiểm tra một điều kiện bieu_thuc2 nữa thì người ta phải đưa

thêm một mệnh đề if nữa vào trong khối mệnh đề else.

bash Csh

if [bieu_thuc]

then cau_lenh

...

elsif [bieu_thuc2]

then cau_lenh

... else

if (bieu_thuc) then cau_lenh

...

else if (bieu_thuc2) then cau_lenh

... else

caulenh

... endif

Page 25: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 25

cau_lenh

... fi

Ví dụ 1: Ví dụ sau sẽ thực hiện kiểm tra tệp tai_lieu có nằm trong thư mục hiện tại

không và in kết quả ra màn hình.

- Đối với bash và pdksh:

if [ -f tai_lieu]

then

echo "Co tệp tai_lieu trong thu mục hien thoi" else

echo "Khong tim thay tệp tai_lieu trong thu muc hien thoi"

fi

- Đối với csh (lưu ý phải có ký tự # ở đầu chương trình) :

#

if ( { -f tai_lieu } ) then

echo "Co tệp tai_lieu trong thu muc hien thoi" else

echo "Khong tim thay tệp tai_lieu trong thu muc hien thoi"

endif

4. Mệnh đề case

Mệnh đề case cho phép so một mẫu (chuỗi ký tự) với nhiều mẫu khác nhau và thực hiện

đoạn mã tương ứng với mẫu trùng khớp. Cú pháp của nó như sau:

bash Cshell

case mau in

mau1)

cau_lenh

...

;;

mau2)

cau_lenh

...

;;

...

*)

cau_lenh

...

switch (mau)

case mau1:

cau_lenh

...

Breaksw

case mau2:

cau_lenh

...

breaksw

...

default:

cau_lenh

...

Page 26: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 26

;;

esac

breaksw

endsw

Trong đó, mau được so sánh lần lượt với các mẫu mau1, mau2... Nếu có một mẫu trùng

khớp thì (các) câu lệnh tương ứng sẽ được thực hiện cho đến khi gặp hai dấu chấm phảy

(;;) bash hoặc breaksw (csh). Nếu không có mẫu nào trùng khớp thì (các) câu lệnh trong

khối * bash hoặc default (csh) được thực hiện.

5. Mệnh đề for

Mệnh đề for thực hiện các câu lệnh trong vòng lặp với một số lần nhất định. Nó có các

dạng sau:

Bash Csh

for bien in danh_sach

do

cau_lenh

...

done

foreach bien (danh_sach)

cau_lenh

...

end

Trong dạng này, mệnh đề for thực hiện mỗi vòng lặp cho mỗi mục trong danh sách

danh_sach. Danh sách này có thể là một biến chứa các từ ngăn cách nhau bởi một dấu

cách hoặc cũng có thể được gõ trực tiếp các từ đó vào dòng lệnh. Mỗi vòng lặp, biến

bien được gán lần lượt một mục (từ) trong danh sách cho đến hết danh sách.

6. Mệnh đề while

Mệnh đề while thực hiện đoạn chương trình bên trong chừng nào mà biểu thức đã cho

còn là Đúng. Cú pháp của nó như sau:

bash Csh

while bieu_thuc

do

menh_de

...

done

while (bieu_thuc)

menh_de

...

end

Page 27: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 27

7. Mệnh đề Until

Cú pháp của mệnh đề until giống với mệnh đề while. Điểm khác biệt là ở chỗ, mệnh đề

while thực hiện vòng lặp chừng nào biểu thức điều kiện còn Đúng, còn mệnh đề until

thực hiện vòng lặp chừng nào biểu thức điều kiện còn Sai. Cú pháp của nó trong bash

như sau :

until bieu_thuc do

cau_lenh

... done

Csh không có mệnh đề này.

IV. BÀI TẬP SHELL

Yêu cầu : Viết một chương trình shell tương tác với hệ thống Linux với yêu cầu:

chương trình shell tạo một menu lựa chọn cho phép

1. hiển thị tên các nhóm có trong hệ thống và các user tồn tại trong từng nhóm

2. hiển thị tên và mật khẩu của tất cả các user tồn tại trong hệ thống

3. hiển thị thời gian đăng nhập của từng user vào hệ thống

4. hiển thị các thông tin về phần cứng của hệ thống

5. kiểm tra xem các phần mềm: pico, vi, openssh server, gcc, tftp, nfs đã cài đặt trên

hệ thống hay chưa? Nếu phần mềm nào chưa cài thì sẽ tự động cài đặt cho hệ thống

Thực hiện: Dưới đây là script thực hiện yêu cầu trên.

#!/bin/bash

until [ "$verify" = n ]

do

echo "Lựa chọn các tính năng theo số thứ tự "

echo "1) hiển thị tên các nhóm có trong hệ thống và các user tồn tại trong từng

nhóm "

echo "2) hiển thị tên và mật khẩu của tất cả các user tồn tại trong hệ thống "

echo "3) hiển thị thời gian đăng nhập của từng user vào hệ thống "

echo "4) hiển thị các thông tin về phần cứng của hệ thống "

Page 28: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 28

echo "5) kiểm tra xem các phần mềm: pico, vi, openssh server, gcc, tftp, nfs đã

cài đặt trên hệ thống hay chưa? Nếu phần mềm nào chưa cài thì sẽ tự động cài đặt

cho hệ thống "

echo "6) Quit"

echo "Please enter your choice"

read pattern

case $pattern in

1) echo "Hiển thị lựa chọn 1"

echo "Danh sách tên nhóm và các user"

cat /etc/passwd | cut -d: -f1,5

# hien thi ten nhom va user trong tung nhom

;;

2) echo " Hiển thị lựa chọn 2"

echo "Tên và mật khẩu các user"

sudo cat /etc/shadow

# login - login name

# password - password in encrypted form, which is 13 to 24 characters long.

# Daysince - Days since [month, day, year] that the password was changed

# Daysafter - Days before the password may be changed

# Daysmust - Days after which the password must be changed

# dayswarn - Days before the password will expire ( A warning to the user)

# daysexpire - Days after the password expires that the account is disabled

# daysince - Days since [month, day, year]that the account is disabled.

# reserved - Reserved field.

;;

3) echo " Hiển thị lựa chọn 3"

echo "Thời gian đăng nhập vào hệ thống của từng user"

last

;;

4) echo " Hiển thị lựa chọn 4"

Page 29: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 29

echo "Thông tin phần cứng"

sudo lshw -short

;;

5) echo "Hiển thị lựa chọn 5 "

echo "Kiểm tra cài đặt phần mềm"

sudo dpkg -l 'pico'

sudo dpkg -l 'vim-common'

sudo dpkg -l 'openssh-server'

sudo dpkg -l 'gcc'

sudo dpkg -l 'tftp'

sudo dpkg -l 'nfs-common'

sudo dpkg -l 'nfs-client'

echo "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

echo "Cài đặt pico"

sudo apt-get install pico

echo "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

echo "Cài đặt vi"

sudo apt-get install vim-common

echo "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

echo "Cài đặt ssh-server"

sudo apt-get install openssh-server

echo "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

echo "Cài đặt gcc"

sudo apt-get install gcc

echo "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

echo "Cài đặt tftp"

Page 30: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 30

sudo apt-get install tftp

echo "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

echo "Cài đặt nfs-common"

sudo apt-get install nfs-common

echo "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

echo "Cài đặt nfs-client"

sudo apt-get install nfs-client

;;

6)

exit 0

;;

esac;

echo "Do you want to continue your choice (y/n)?"

read verify

done

Kết quả :

Menu hiển thị các lựa chọn

Lựa chọn 1: Hiển thị các nhóm và user trong từng nhóm

Page 31: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 31

Lựa chọn 2: Hiển thị tên và mật khẩu từng user

Mật khẩu đã được mã hóa.

Lựa chọn 3: Hiển thị thời gian đăng nhập từng user

Page 32: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 32

Lựa chọn 4: Hiển thị thông tin phần cứng

Lựa chọn 5: Kiểm tra các gói phần mềm và cài đặt

- Dưới đây là kiểm tra các gói phần mềm đã cài đặt hay

chưa

Page 33: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 33

- Nếu chưa được cài đặt thì hệ thống sẽ tự động cài đặt

Page 34: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 34

- Hệ thống sẽ hỏi bạn có muốn cài đặt tiếp phần mềm

không.

PHẦN II. LẬP TRÌNH C TRÊN LINUX

A. Thư viện liên kết trên Linux

Hình thức đơn giản nhất của thư viện là tập hợp các tập tin “.o” do trình biên dịch tạo ra ở

bước biên dịch với tùy chọn -c.

a. Thư viện liên kết tĩnh

i. Khái niệm thư viện liên kết tĩnh

Thư viện liên kết tĩnh 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 các hàm trong thư viện đưa vào chương trình

chính.

ii. Tạo thư viện liên kết tĩnh

Gồm 3 bước cơ bản:

Bước 1. Viết các hàm cho thư viện.

Bước 2. Tạo các file đối tượng từ các hàm thư viện vừa viết.

Page 35: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 35

Bước 3. Nén các file đối tượng vừa tạo thành một file thư viện “.a”,

tiếp đầu ngữ “lib”.

Ví dụ: Tạo một thư viện liên kết tĩnh, chứa các hàm với chức năng như sau:

- nhap3so: cho nhập vào 3 số thực.

- gptb2: giải phương trình ax^2+bx+c=0, (a # 0)

- nhapchuoi: cho nhập vào chuỗi kí tự.

- xulychuoi: định dạng cơ bản chuỗi kí tự.

Bước 1. Viết các hàm cho thư viện

gedit nhap3so.c

//code nhap3so.c

#include<stdio.h>

void nhap3so()

{

float a,b,c;

printf("Ham nhap 3 so thuc : \n");

printf("Nhap cac he so : \n");

printf("Nhap a:\n");

scanf("%f",&a);

printf("Nhap b:\n");

scanf("%f",&b);

printf("Nhap c:\n");

scanf("%f",&c);

}

//end code nhap3so.c

gedit gptb2.c

//code gptb2.c

#include<stdio.h>

#include<math.h>

void gptb2()

Page 36: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 36

{

float a,b,c;

float x,x1,x2;

float delta=b*b-4*a*c;

if(delta>0)

{

x1=(-b+sqrt(delta))/(2*a);

x2=(-b-sqrt(delta))/(2*a);

printf("Phuong trinh co 2 nghiem phan biet:\n");

printf("x1=%.2f , x2=%.2f ",x1,x2);

}

else if(delta==0)

{

x=-b/(2*a);

printf("Phuong trinh co nghiem kep:\n");

printf("x1=x2=%.2f ",x);

}

else

{

printf("Phuong trinh vo nghiem !\n");

}

}//end code gptb2.c

gedit nhapchuoi.c

//code nhapchuoi.c

#include <string.h>

#include <stdio.h>

char s[100];

void nhapchuoi()

{

Page 37: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 37

puts("Ham nhap chuoi ki tu : \n");

puts("Nhap vao mot chuoi ki tu: \n");

while(getchar() != '\n');

gets(s);

}

//end code nhapchuoi.c

gedit xulychuoi.c

//code xulychuoi.c

#include<string.h>

#include<ctype.h>

#include<stdio.h>

char s[100];

void xulychuoi()

{

int len_s,i,j;

len_s=strlen(s);

printf("Do dai chuoi la %d\n",len_s);

printf("\n");

////////////////////////////

for(i=0;i<len_s;i++)

{

if(s[i]>='A'&&s[i]<='Z')

s[i]=s[i]+32;

}

puts("Chuyen doi chuoi thanh chu thuong\n");

puts(s);

printf("\n");

/////////////////////////////

for(j=0;j<len_s;j++)

Page 38: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 38

{

if(j==0)

s[0]=toupper(s[0]);

if(s[j]==32)

s[j+1]=toupper(s[j+1]);

}

puts("Viet hoa ki tu dau trong chuoi:\n");

puts(s);

printf("\n");

/////////////////////////////

for(j=0;j<len_s;j++)

{

if(s[j]>='a'&&s[j]<='z')

s[j]=s[j]-32;

}

puts("Chuyen doi chuoi thanh chu hoa:\n");

puts(s);

printf("\n");

}

//end code xulychuoi.c

Bước 2. Tạo các file đối tượng “.o” từ các hàm vừa viết.

gcc -c nhap3so.c gptb2.c xulychuoi.c nhapchuoi.c

Bước 3. Nén các file đối tượng vừa tạo thành một file thư viện “.a”, tiếp đầu

ngữ “lib”. Vd: libstatic.a

ar cvr libstatic.a nhap3so.o gptb2.o nhapchuoi.o xulychuoi.o

Ứng dụng thư viện liên kết tĩnh libstatic.a :

1. Viết chương trình giải phương trình bậc hai.

2. Viết chương trình tổng hợp:

- Giải phương trình bậc hai

Page 39: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 39

- Xử lý chuỗi cơ bản

1. Chương trình giải phương trình bậc hai

a. Tạo file tiêu đề “.h” - khai báo thuộc tính cho các hàm sử dụng trong

chương trình.

gedit header_gpt.h

//code header_gpt.h

void nhap3so();

void gptb2();

//end code header_gpt.h

b. Tạo file và viết code chương trình chính

gedit main_gpt.c

//code main_gpt.c

#include "header_gpt.h"

void main(void)

{

nhap3so();

gptb2();

}

//end code main_gpt.c

c. Biên dịch chương trình chính liên kết với thư viện tĩnh libstatic.a

gcc main_gpt.c -o main_gpt libstatic.a -lm

d. Thực thi chương trình

./main_gpt

2. Chương trình tổng hơp

- Giải phương trình bậc 2: ax^2+bx+c =0 (a#0)

- Xử lý chuỗi cơ bản

a. Tạo file tiêu đề “.h”- khai báo thuộc tính cho các hàm sử dụng trong

chương trình

gedit header.h

//code header.h

Page 40: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 40

void nhap3so();

void gptb2();

void nhapchuoi();

void xulychuoi();

//end code header.h

b. Tạo file và viết code chương trình chính

gedit main_th.c

//code main_th.c

#include <stdio.h>

#include <string.h>

#include "header.h"

void main(void)

{

int choice;

char exit;

do

{

printf("Menu Chuong Trinh\n");

printf("1) Xu ly chuoi ky tu\n");

printf("2) Giai phuong trinh ax^2+bx+c=0\n");

printf("3) Thoat chuong trinh\n");

printf("Lua chon yeu cau : \n");

scanf("%d",&choice);

switch(choice)

{

case 1: nhapchuoi();

xulychuoi();

break;

case 2: nhap3so();

gptb2();

Page 41: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 41

break;

case 3:

break;

default : printf("Phai nhap 1, 2 hoac 3\n");

};

printf("Thoat chuong trinh ? (y/n)\n");

while(getchar() != '\n');

scanf("%c",&exit);

}while(exit == 'n');

}

//end code main_th.c

c. Biên dịch chương trình chính liên kết với thư viện tĩnh libstatic.a

gcc main_th.c -o main_th libstatic.a -lm

d. Thực thi chương trình

./main_th

Ưu điểm: Chương trình sử dụng thư viện liên kết tĩnh có thể chạy độc lập với thư

viện sau khi được biên dịch – chạy được trên các máy tính khác nhau.

Nhược điểm:

- Tốn không gian ổ đĩa:

o Toàn bộ mã thực thi của các hàm trong thư viện sẽ được nhúng vào file

thực thi của chương trình chính.

o Nhiều chương trình khác nhau không thể cùng dùng chung một thư viện

duy nhất.

o Có những hàm trong thư viện mà chương trình chính không dùng đến

cũng được liên kết với chương trình chính khi biên dịch.

- Hạn chế trong việc sửa đổi, nâng cấp thư viện liên kết tĩnh và các chương

trình sử dụng thư viện liên kết tĩnh đó:

Page 42: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 42

o Khi muốn sửa đổi hoặc nâng cấp thư viện thì phải thay đổi hoặc thêm

mã nguồn cho các hàm trong thư viện, dẫn đến việc phải biên dịch lại

từ đầu mã nguồn để tạo ra file thư viện “.a”.

o Chương trình sử dụng thư viện liên kết tĩnh nếu muốn tận dụng những

tính năng mới của thư viện thì cũng phải được biên dịch lại.

b. Thư viện liên kết động

i. Khái niệm thư viện liên kết động

Thư viện liên kết động là thư viện mà các hàm trong thư viện không

được trực tiếp đưa vào chương trình lúc biên dịch và liên kết.

Trình liên kết chỉ lưu thông tin tham chiếu đến các hàm trong thư viện.

Vào lúc chương trình thực thi, hệ điều hành sẽ nạp các chương trình

liên kết cần tham chiếu vào bộ nhớ.

ii. Tạo thư viện liên kết động

Gồm 3 bước cơ bản:

Bước 1. Viết các hàm cho thư viện.(tương tự như thư viện liên

kết tĩnh)

Bước 2. Tạo các file đối tượng “.o” từ các hàm vừa viết để đưa

vào thư viện liên kết động ( sử dụng gcc với tùy chọn -fpic).

Bước 3. Tạo file thư viện liên kết động (“.so”, tiếp đầu ngữ

“lib”) , từ các file đối tượng vừa tạo, sử dụng gcc với tùy chọn -

shared.

Ví dụ: Tạo một thư viện liên kết động, chứa các hàm với chức năng như sau:

- nhap3so: cho nhập vào 3 số thực.

- gptb2: giải phương trình ax^2+bx+c=0, (a # 0)

- nhapchuoi: cho nhập vào chuỗi kí tự.

- xulychuoi: định dạng cơ bản chuỗi kí tự.

Bước 1. Viết các hàm cho thư viện.

gedit nhap3so.c

//code nhap3so.c

Page 43: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 43

#include<stdio.h>

float a,b,c;

void nhap3so()

{

printf("Ham nhap 3 so thuc : \n");

printf("Nhap cac he so : \n");

printf("Nhap a:\n");

scanf("%f",&a);

printf("Nhap b:\n");

scanf("%f",&b);

printf("Nhap c:\n");

scanf("%f",&c);

}

//end code nhap3so.c

gedit gptb2.c

//code gptb2.c

#include<stdio.h>

#include<math.h>

float a,b,c;

void gptb2()

{

float x,x1,x2;

float delta=b*b-4*a*c;

if(delta>0)

{

x1=(-b+sqrt(delta))/(2*a);

x2=(-b-sqrt(delta))/(2*a);

printf("Phuong trinh co 2 nghiem phan biet:\n");

printf("x1=%.2f , x2=%.2f ",x1,x2);

Page 44: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 44

}

else if(delta==0)

{

x=-b/(2*a);

printf("Phuong trinh co nghiem kep:\n");

printf("x1=x2=%.2f ",x);

}

else

{

printf("Phuong trinh vo nghiem !\n");

}

}

//end code gptb2.c

gedit nhapchuoi.c

//code nhapchuoi.c

#include <string.h>

#include <stdio.h>

char s[100];

void nhapchuoi()

{

puts("Ham nhap chuoi ki tu : \n");

puts("Nhap vao mot chuoi ki tu: \n");

while(getchar() != '\n');

gets(s);

}

//end code nhapchuoi.c

gedit xulychuoi.c

//code xulychuoi.c

Page 45: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 45

#include<string.h>

#include<ctype.h>

#include<stdio.h>

char s[100];

void xulychuoi()

{

int len_s,i,j;

len_s=strlen(s);

printf("Do dai chuoi la %d\n",len_s);

printf("\n");

////////////////////////////

for(i=0;i<len_s;i++)

{

if(s[i]>='A'&&s[i]<='Z')

s[i]=s[i]+32;

}

puts("Chuyen doi chuoi thanh chu thuong\n");

puts(s);

printf("\n");

/////////////////////////////

for(j=0;j<len_s;j++)

{

if(j==0)

s[0]=toupper(s[0]);

if(s[j]==32)

s[j+1]=toupper(s[j+1]);

}

puts("Viet hoa ki tu dau trong chuoi:\n");

puts(s);

printf("\n");

Page 46: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 46

/////////////////////////////

for(j=0;j<len_s;j++)

{

if(s[j]>='a'&&s[j]<='z')

s[j]=s[j]-32;

}

puts("Chuyen doi chuoi thanh chu hoa:\n");

puts(s);

printf("\n");

}

//end code xulychuoi.c

Bước 2. Tạo các file đối tượng “.o” từ các hàm vừa viết để đưa vào thư viện

liên kết động ( sử dụng gcc với tùy chọn -fpic).

gcc -c -fpic nhap3so.c gptb2.c nhapchuoi.c xulychuoi.c

Bước 3. Tạo file thư viện liên kết động (“.so”, tiếp đầu ngữ “lib”) , từ các file

đối tượng vừa tạo, sử dụng gcc với tùy chọn -shared.

gcc -shared nhap3so.o gptb2.o nhapchuoi.o xulychuoi.o -o libdynamic.so

(trong đó “libdynamic.so” là tên thư viện liên kết động)

Ứng dụng thư viện liên kết động libdynamic.so:

1. Viết chương trình giải phương trình bậc hai.

2. Viết chương trình tổng hợp:

- Giải phương trình bậc hai

- Xử lý chuỗi cơ bản

1. Chương trình giải phương trình bậc hai

a. Tạo file và viết code chương trình chính

gedit main_gpt2.c

//code main_gpt.c

void main(void)

{

Page 47: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 47

nhap3so();

gptb2();

}

//end code main_gpt2.c

b. Biên dịch chương trình sử dụng thư viện liên kết động libdynamic.so

gcc main_gpt2.c -o main_gpt2 -L. -ldynamic -lm

Tùy chọn -L. -ldynamic : chỉ ra cho trình liên kết tìm đến thư viện dynamic trong thư mục

hiện hành để lưu thông tin tham chiếu các hàm dùng trong chương trình chính.

c. Chạy file thực thi vừa tạo

- Định đường dẫn biến môi trường chỉ đến thư mục hiện hành – nơi chứa thư

viện libdynamic.so cần tham chiếu.

LD_LIBRARY_PATH=.:

export LD_LIBRARY_PATH

- Chạy file thực thi:

./main_gpt2

2. Chương trình tổng hợp

- Xử lý chuỗi kí tự cơ bản nhập từ bàn phím

- Giải phương trình bậc hai: ax^2+bx+c=0, (a#0)

a. Tạo file và viết code chương trình chính

gedit main_th2.c

//code main_th2.c

#include <stdio.h>

#include <string.h>

void main(void)

{

int choice;

char exit;

do

{

Page 48: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 48

printf("Menu Chuong Trinh\n");

printf("1) Xu ly chuoi ky tu\n");

printf("2) Giai phuong trinh ax^2+bx+c=0\n");

printf("3) Thoat chuong trinh\n");

printf("Lua chon yeu cau : \n");

scanf("%d",&choice);

switch(choice)

{

case 1: nhapchuoi();

xulychuoi();

break;

case 2: nhap3so();

gptb2();

break;

case 3:

break;

default : printf("Phai nhap 1, 2 hoac 3\n");

};

printf("Thoat chuong trinh ? (y/n)\n");

while(getchar() != '\n');

scanf("%c",&exit);

}while(exit == 'n');

}

//end code main_th2.c

b. Biên dịch chương trình sử dụng thư viện liên kết động libdynamic.so

gcc main_th2.c -o main_th2 -L. -ldynamic -lm

c. Chạy file thực thi vừa tạo

./main_th2

Ưu điểm:

- Tiết kiệm không gian ổ đĩa:

Page 49: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 49

o File thực thi của chương trình chính không chứa mã thực thi của các

hàm trong thư viện.

o Nhiều chương trình khác nhau có thể cùng dùng chung một thư viện

duy nhất.

- Chương trình sử dụng thư viện liên kết động không phải được biên dịch lại mà

vẫn có thể sử dụng những tính năng mới của thư viện (trong trường hợp thư

viện đó được sửa đổi, nâng cấp).

Khuyết điểm:

- Chương trình sử dụng thư viện liên kết động không thể chạy độc lập với thư

viện – chương trình phụ thuộc hoàn toàn vào thư viện.

- Hạn chế khi muốn sửa đổi hoặc nâng cấp: Khi muốn sửa đổi hoặc thêm hàm

cho thư viện, vẫn phải thực hiện lại các bước như khi tạo thư viện ban

đầu(tương tự thư viện liên kết tĩnh).

Kết luận về ưu, nhược điểm trong việc lập trình ngôn ngữ C trên Linux sử dụng thư viện

liên kết động và liên kết tĩnh :

Kích thước file thực thi:

Xem lại các chương trình trong 2 video trước, cùng một mã nguồn nhưng việc

sử dụng loại thư viện liên kết khác nhau dẫn đến kích thước file thực thi khác

nhau: chương trình sử dụng thư viện liên kết tĩnh luôn có kích thước file lớn

hơn chương trình sử dụng thư viện liên kết động.

File thực thi Thư viện liên kết tĩnh Thư viện liên kết động

main_gpt 7.2KB 7.0KB

main_th 7.5KB 7.2KB

Khả năng độc lập của chương trình thực thi với thư viện:

o Chương trình sử dụng thư viện liên kết tĩnh có khả năng chạy độc lập với thư

viện sau khi được biên dịch.

o Chương trình sử dụng thư viện liên kết động phụ thuộc vào thư viện, không

thể chạy độc lập với thư viện.

Khả năng chỉnh sửa, thay đổi của chương trình ứng dụng:

Page 50: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 50

o Do tính độc lập của chương trình sử dụng thư viện liên kết tĩnh nên nếu muốn

chỉnh sửa chương trình ứng dụng thì cần phải biên dịch lại chương trình cùng

với thư viện mà nó liên kết.

o Chương trình sử dụng thư viện liên kết động có thể tận dụng trực tiếp ngay

những sự thay đổi của thư viện mà nó liên kết, không cần phải được biên dịch

lại.

Nói tóm lại, ta có bảng sau:

Chương trình ứng dụng Thư viện liên kết tĩnh Thư viện liên kết động

Kích thước Lớn Nhỏ

Tính độc lập Có Không

Khả năng chỉnh sửa, nâng cấp Hạn chế Hỗ trợ

Tùy vào mục đích, khả năng, quy mô cũng như phạm vi chương trình ứng dụng mà

người lập trình cần cân nhắc trong việc lựa chọn sử dụng loại thư viện liên kết cho phù hợp

nhất.

B. Makefile: sử dụng trong biên dịch mã nguồn.

Câu lệnh make thường được ít người dùng quan tâm đến. Thông thường câu lệnh này

và Makefile nằm trong nhóm mã nguồn hỗ trợ biên dịch và liên kết mã nguồn trong file thực

thi.

Tuy nhiên nó còn có thể được sử dụng để thực hiện nhiều tính năng khác ngoài việc

xử lý mã nguồn.

Makefile là một chuỗi lệnh thực thi, làm việc trên các phần phụ của file mục tiêu. Ví

dụ, bạn có thể chạy lệnh make install và lệnh này sẽ kiểm tra cập nhật những đối tượng

được yêu cầu trước tiên, như mục tiêu compile và các thành phần phụ của nó. Điều này làm

cho lệnh make trở thành một lệnh rất linh hoạt. Điều này cũng có nghĩa bạn có thể sử dụng

nó với nhiều file ngoại trừ file mã nguồn; bạn có thể sử dụng Makefile để copy file (cục bộ

hay từ xa), kiểm soát phiên bản, xóa file, hay những lệnh khác có thể sử dụng khi xử lý file.

Trong bài này chúng ta tập trung vào mục tiêu sử dụng Makefile trong biên dịch mã

nguồn đối với lập trình C.

1. Vì sao ta phải dùng Makefile?

Các chương trình quá lớn:

Page 51: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 51

- Có rất nhiều dòng code

- Các thành phần phức tạp.

- Nhiều hơn 1 người lập trình

Các vấn đề:

- Các file dài khó để quản lí (cho cả người lập trình và máy).

- Mọi thay đổi đề đòi hỏi sự biên dịch dài. Nhiều người lập trình không thể chỉnh

sửa các file đòng thời.

Giải pháp: chia project(dự án/công trình) thành các file.

Mục tiêu:

- Phân chia tốt các thành phần

- Tối thiểu sự biên dịch khi có gì đó thay đổi.

- Dễ dàng bảo trì cấu trúc project, sự phụ thuộc và sự sáng tạo.

. Đ

Makefile

- ,

- :

CC=gcc # the C compiler is gcc

CFLAGS=-g -Wall -I/usr/include/libxml2

LIBS=-lxml2

tut_prog: main.o aux.o

$(CC) $(LIBS) main.o aux.o -o tut_prog

main.o: main.c

$(CC) -c $(CFLAGS) main.c

aux.o: aux.c

$(CC) -c $(CFLAGS) aux.c

.

N)

, CFLAGS, LIBS

Page 52: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 52

.

:

+CC „gcc‟

CXX ++‟

CPP $(cc) –e‟

RM –f‟

CFLAGS

LDFLAGS

Page 53: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 53

2.

target: prerequisites….

command

...

...

- target thường là tên của file được tạo ra bởi chương trình, hoặc cũng có thể là

các chỉ định để thực thi một hoặc một loạt tác vụ nào đó. Các target không

được bắt đầu bằng dấu '.'

- prerequisite là file hoặc các file đầu vào hoặc phụ thuộc để tạo ra target. target

thường phụ thuộc vào các file này, khi các file này thay đổi (do chỉnh sửa mã

nguồn->thời gian lưu cửa file bị thay đổi) thì target sẽ được biên dịch lại.

- command là lệnh hoặc tập lệnh mà trình make sẽ thực thi. Một rule (quy tắc)

có thể có nhiều lệnh (command), mỗi lệnh thường được viết trên một dòng.

Chú ý: trước mỗi dòng lệnh bạn cần phải có dấu tab. Dấu '\' ở cuối dòng để

quy định dòng dưới tiếp theo thực chất cũng là dòng trên, vì dòng trên dài quá,

nên chúng ta có thể ngắt xuống dưới bằng dấu này.

Các biến:

Các biến được dùng để rút gọn, khai báo có dạng sau:

var=text1text2..textn

Khi sử dụng để tham chiếu ta dùng theo dạng $(var) .

.

-

- .

:

all

check

clean

distclean

dist (tar.gz)

install )

uninstall

1. Sử dụng các biến trong Makefile

Page 54: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 54

Tạo ra Makefile: Nội dung của Makefile của project như sau:

Code:

USER_DIR=..

LIB_DIR=$(USER_DIR)/libraries

MAIN_FILE_DIR=$(USER_DIR)/mainFile

INC=-I$(LIB_DIR)

#compiler

CC=gcc

FLAG= -Wall-g-W

#source

STUB=$(LIB_DIR)/ipc.c $(LIB_DIR)/person.c

#nameofmainfile

MAIN_FILE_NAME=sample1

#object

OBJECT= ipc.o person.o

#The Target

run: ready code

$(CC)$(INC)$(FLAG)$(MAIN_FILE_NAME).o$(OBJECT)-o run

ready:

$(CC)$(INC)$(FLAG) -c $(STUB)

code:

$(CC) $(INC) $(FLAG) -c $(MAIN_FILE_DIR)/$(MAIN_FILE_NAME).c

clean

rm -rf *.o run

Những từ viết in hoa đó là các biến môi trường (such as: USER_DIR, GXX, FLAG,

MAIN_FILE_NAME,....) sau dấu = của các biến môi trường là nội dung được gán

cho các biến

Vídụ:

USER_DIR=.. <-- biến USER_DIR với nội dung là ".."

LIB_DIR= $(USER_DIR)/libraries <-- biến LIB_DIR với nội dung là "../libraries"

Page 55: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 55

Một số lời khuyên khi tạo Makefile:

- Bạn nên tạo ra biến môi trường:

Ở ví dụ trên nếu không dùng biến môi trường mà viết thẳng trong các target dòng

lệnh luôn, tức là Makefile của trở thành:

Code:

run: ready code

gcc -I../libraries -Wall -g -W sample1.o ipc.o person.o -o run

ready:

gcc -I../libraries -Wall -g -W -c ../libraries/ipc.c ../libraries/person.c

code:

gcc -I../libraries -Wall -g -W -c ../mainFile/sample1.c

clean:

rm -rf *.o run

thì Makefile vẫn hoạt động bình thường tuy nhiên make file này chỉ có thể dịch cho

mỗi file sample1.c hoặc nếu muốn thay thành sample2.c thì phải thay cả ở run,code.

- Nên tạo ra Target có chức năng tương tự target clean:

Khi làm việc với project lớn thì việc tạo clean khá quan trọng vì khi gọi nó sẽ

xóa đi những gì được gọi là rác trong quá trình build như là những file object

hoặc file executable cũ chẳng hạn.

3. Ví dụ Demo sử dụng Makefile

Viết chương trình cho phép nhập vào một số nguyên, yêu cầu xuất ra màn hình số

vừa nhập là chẵn hay lẻ ?

Các bước thực hiện:

Tạo file main.c // chương trình chính

Code:

#include <stdio.h>

#include "header.h"

void main(void)

{

int num;

printf("Nhap vao mot so: \n");

Page 56: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 56

scanf("%d",&num);

if(odd_even(num))

printf("%d la so chan \n",num);

else

printf("%d la so le \n",num);

printf("\n");

}

1. Tạo file function.c // hàm phân biệt chẵn lẻ

Code:

int odd_even(int x)

{

if(x % 2 == 0)

return 1;

else

return 0;

}

2. Tạo file header.h // khai báo nguyên hàm nguyên mẫu

Code:

int odd_even(int x);

Tạo file Makefile // nội dung make

- Code không sử dụng biến:

main: main.o function.o

gcc main.o function.o -o main

main.o: main.c

gcc -c main.c

function.o: function.c header.h

gcc -c function.c

clearn:

rm *.o

Page 57: Lập Trình C và Shell Trên Linux

Môn học: Lập trình hệ thống

Phần: Hệ điều hành Linux Trang 57

- Code có sử dụng biến:

USER_DIR=..

WORK_DIR=$(USER_DIR)/Desktop/makefile

CC=gcc

OBJECT=main.o function.o

MAIN_FILE=main

MAIN_FILE: $(OBJECT)

$(CC) $(OBJECT) -o $(MAIN_FILE)

$(WORK_DIR)/main.o: $(WORK_DIR)/main.c

CC -c $(WORK_DIR)/main.c

$(WORK_DIR)/function.o: $(WORK_DIR)/function.c

CC -c $(WORK_DIR)/function.c

clearn:

rm *.o

3. Từ Terminal với đường dẫn trong thư mục các file vừa tạo, gõ lệnh :

a. make // thực thi Makefile

b. ./main // chạy chương trình

c. make clean // xóa file .o ( không cần thiết)