Tài liệu thực hành lần 3 | Hệ điều hành
Sau khi cài đặt, vim sẽ thuong đuợc đặt tại /user/bin/vim (sử dụng which vim để biết chính xác vị trí gcc trong moi máy tính). Mát chuong trình đi kèm là vimtutor sẽ đuợc tự đáng cài vào hệ thống, chạy vimtutor và hoàn thành các bài huớng dẫn làm quen với vim. Bài giảng giúp bạn tham khảo, củng cố kiến thức và ôn tập đạt kết quả cao
Trường: Trường Đại học Công nghệ Thông tin, Đại học Quốc gia Thành phố Hồ Chí Minh
Thông tin:
Tác giả:
Preview text:
Đ¾I HàC QUÞC GIA TP Hà CHÍ MINH
TR¯àNG Đ¾I HàC CÔNG NGHÞ THÔNG TIN óoô
Tài lißu h°ßng dẫn thāc hành HÞ ĐIÀU HÀNH
Biên soạn: ThS Phan Đình Duy ThS Nguyễn Thanh Thiện KS Trần Đại D°¡ng KS Trần Hoàng Lác L¯U HÀNH NàI Bà
Thành phß Há Chí Minh – MĀC LĀC BÀI 3.
TI¾N TRÌNH VÀ TIÂU TRÌNH ......................................... 1 3.1
Māc tiêu ............................................................................................................. 1 3.2
Nái dung thāc hành .......................................................................................... 1 3.3
Sinh viên chuẩn bß ............................................................................................ 2 3.4
H°ßng dẫn thāc hành .................................................................................... 20 3.5
Bài tập ôn tập .................................................................................................. 51 NàI QUY THĀC HÀNH
1. Sinh viên tham dự đầy đủ các buổi thực hành theo quy định
của giảng viên h°ớng dẫn (GVHD) (6 buổi với lớp thực
hành cách tuần hoặc 10 buổi với lớp thực hành liên tục).
2. Sinh viên phải chuẩn bị các nái dung trong phần viên chuẩn bị= tr°ớc khi đến lớp. GVHD sẽ kiểm tra bài
chuẩn bị của sinh viên trong 15 phút đầu của buổi học (nếu
không có bài chuẩn bị thì sinh viên bị tính vắng buổi thực hành đó).
3. Sinh viên làm các bài tập ôn tập để đ°ợc cáng điểm thực
hành, bài tập ôn tập sẽ đ°ợc GVHD kiểm tra khi sinh viên
có yêu cầu trong buổi học liền sau bài thực hành đó. Điểm
cáng tối đa không quá 2 điểm cho mßi bài thực hành.
Bài 3. TI¾N TRÌNH VÀ TIÂU TRÌNH 3.1 Māc tiêu
Sinh viên làm quen với lập trình trên Hệ điều hành
Ubuntu thông qua trình soạn thảo vim, trình biên dịch gcc và trình gỡ lßi gdb
Thực hành với tiến trình
Thực hành với tiểu trình thông qua th° viện pthread
Giới thiệu về c¡ chế truyền thông: signal
3.2 Nái dung thāc hành
Sử dụng trình soạn thảo vim để soạn thảo mã nguồn
Sử dụng trình biên dịch gcc để biên dịch từ tệp tin mã
nguồn sang tệp tin có thể thực thi
Sử dụng trình gỡ lßi gdb để gỡ lßi ch°¡ng trình Tạo, dừng tiến trình
Tạo, dừng, hợp và gỡ tiểu trình với th° viện pthread
Truyền thông giữa các tiến trình bằng c¡ chế signal 1
3.3 Sinh viên chuẩn bß
3.3.1 Trình so¿n thÁo văn bÁn vim
Trình soạn thảo văn bản thuần túy không sử dụng các định
dạng văn bản để trình bày, những văn bản đ°ợc tạo ra từ trình
soạn thảo này rất nhẹ, đ°ợc đọc dễ dàng mà không cần xử lý
nhiều. Trong bài thực hành này, vim (Visual Improved) đ°ợc sử
dụng làm công cụ thực hành. Sinh viên có thể cài đặt vim và các
gói liên quan bằng câu lệnh sau: apt-get install vim
Sau khi cài đặt, vim sẽ th°ßng đ°ợc đặt tại /user/bin/vim (sử
dụng which vim để biết chính xác vị trí gcc trong mßi máy tính).
Mát ch°¡ng trình đi kèm là vimtutor sẽ đ°ợc tự đáng cài vào hệ
thống, chạy vimtutor và hoàn thành các bài h°ớng dẫn làm quen với vim.
3.3.2 Trình biên dßch gcc
Trình biên dịch (compiler) là phần mềm biên dịch từ mã
nguồn (ch°¡ng trình đ°ợc viết bằng ngôn ngữ lập trình cấp cao)
thành các chußi bit (ch°¡ng trình có thể thực thi đ°ợc trên máy
tính). Trong bài thực hành này, gcc (GNU C Compiler) đ°ợc sử
dụng làm công cụ thực hành. Sinh viên có thể cài đặt gcc và các
gói liên quan bằng câu lệnh sau: 2
apt-get install build-essential
Sau khi cài đặt, gcc sẽ th°ßng đ°ợc đặt tại /user/bin/gcc (sử
dụng which gcc để biết chính xác vị trí gcc trong mßi máy tính).
Hình 3-1 trình bày quá trình biên dịch mát ch°¡ng trình từ mã
nguồn thành ch°¡ng trình có thể thực thi đ°ợc trên máy tính. 3
Hình 3-1 Quá trình biên dịch
Quá trình từ tệp mã nguồn tới tệp đối t°ợng có thể trình bày chi tiết h¡n trong Hình 3-2.
Hình 3-2 Quá trình biên dịch chi tiết 4
Bá tiền xử lý (Preprocessor) sẽ lấy bản sao của tệp mã nguồn
(*.c) nằm tại th° mục của project và sao chép nái dung các tệp
tiêu đề (*.h) nằm tại /usr/include vào bản sao ấy, bản sao này trá
thành mát ch°¡ng trình hoàn chỉnh á mức ngôn ngữ lập trình cấp
cao. Tiếp theo, trình biên dịch sẽ biên dịch bản sao này thành mát
ch°¡ng trình á mức hợp ngữ (*.asm) theo kiến trúc tập lệnh mà
máy tính đang sử dụng. Sau đó, trình biên dịch hợp ngữ
(Assembler) sẽ thông dịch ch°¡ng trình á mức hợp ngữ này thành
các tệp đối t°ợng (*.o). Cuối cùng, trình liên kết (Linker) sẽ liên
kết các tệp đối t°ợng và các th° viện (*.a, *.so, *.sa) nằm tại
/usr/lib hoặc /lib để tạo thành mát ch°¡ng trình á mức nhị phân có
thể thực thi đ°ợc trên máy tính:
Các tệp mã nguồn (*.c) là các tệp tin do ng°ßi viết
ch°¡ng trình viết nhằm phục vụ mục đích chuyên biệt nào
đó và th°ßng đ°ợc cập nhật trong quá trình phát triển phần mềm.
Các tệp tiêu đề (*.h) là các tệp tin dùng để định nghĩa hàm
và các khai báo cần thiết cho quá trình biên dịch. Dựa vào
những thông tin này, trình biên dịch sẽ đ°a ra cảnh báo
hoặc lßi cú pháp, kiểu dữ liệu, hoặc tạo ra các tệp đối t°ợng (*.o). 5
Các tệp đối t°ợng (*.o) là các tệp tin chứa các khối mã nhị phân thuần túy.
Các tệp tin th° viện (lib*.a, lib*.sa, lib*.so) là các tệp tin
thiết yếu để biên dịch ch°¡ng trình. Trên môi tr°ßng
Linux có 2 loại th° viện liên kết là th° viện liên kết tĩnh
và th° viện liên kết đáng:
❖ 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 bản sao toàn bá mã thực thi
của hàm trong th° viện đ°a vào ch°¡ng trình
chính. Ch°¡ng trình sử dụng th° viện này chạy
đác lập với th° viện sau khi biên dịch xong. Khi
nâng cấp và sửa đổi, muốn tận dụng những chức
năng mới của th° viện thì chúng ta phải biên dịch
lại ch°¡ng trình, ngoài ra việc sử dụng th° viện
liên kết tĩnh dẫn đến tiêu tốn không gian bá nhớ
và khó nâng cấp ch°¡ng trình.
❖ Th° viện liên kết đáng (lib*.so) là các th° viện
không đ°ợc đ°a trực tiếp vào ch°¡ng trình lúc
biên dịch và liên kết, trình liên kết (linker) chỉ l°u
thông tin tham chiếu đến các hàm trong th° viện
liên kết đáng. Khi ch°¡ng trình thực thi, Hệ điều 6
hành sẽ nạp các ch°¡ng trình liên kết cần tham
chiếu vào bá nhớ, nhß đó, nhiều ch°¡ng trình có
thể sử dụng chung các hàm trong mát th° viện duy nhất.
Sử dụng vim để soạn ch°¡ng trình hello.c nh° sau:
/*######################################
# University of Information Technology # # IT007 Operating System # # , # # File: hello.c #
######################################*/ #include int main() { printf("Hello, I am ,\n");
printf("Welcome to IT007!\n"); return 0; }
Biên dịch và chạy ch°¡ng trình bằng 2 dòng lệnh sau: 7 $ gcc hello.c -o hello $ ./hello
Trong đó gcc là tên lệnh, hello.c là tệp tin đầu vào và hello là
tệp tin đầu ra. ./hello dùng để chạy ch°¡ng trình. Hãy kiểm chứng
kết quả hiển thị trên màn hình là: Hello, I am , Welcome to IT007!
Nếu muốn quan sát rõ h¡n quá trình biên dịch thì có thể sử
dụng các lệnh t°¡ng ứng sau: Māc đích Lßnh
Xem tệp tin tạm (sau gcc -E hello.c -o hello_tmp.c Preprocessor)
Xem tệp tin hợp ngữ (sau gcc -S hello.c Compiler)
Xem tệp tin đối t°ợng (Sau gcc -c hello.c Assembler)
Tạo tệp tin thực thi từ tệp tin đối gcc hello.o -o hello t°ợng 8
Bây giß hãy quay lại với ch°¡ng trình hello của chúng ta với
cách mà các lập trình viên áp dụng trong thực tế bằng cách thêm
hàm main.c và chuyển ch°¡ng trình hello.c á trên thành mát th° viện nh° sau:
/*######################################
# University of Information Technology # # IT007 Operating System # # , # # File: hello.h #
######################################*/ #ifndef __HELLO_H #define __HELLO_H void hello(); #endif
/*######################################
# University of Information Technology # # IT007 Operating System # 9 # , # # File: hello.c #
######################################*/ #include #include "hello.h" void hello() { printf("Hello, I am ,\n");
printf("Welcome to IT007!\n"); }
/*######################################
# University of Information Technology # # IT007 Operating System # # , # # File: main.c #
######################################*/ #include "hello.h" 10 int main() { hello(); return 0; }
Trong tệp hello.c á trên, có mát sự khác biệt nhỏ tại chỉ thị
#include, sự khác nhau giữa #include và #include
tr°ớc quá trình biên dịch:
#include : Bá tiền xử lý (Pre-processor) sẽ chỉ
tìm kiếm tệp tin tiêu đề (.h) trong th° mục chứa tệp tiêu
đề của th° viện ngôn ngữ C. Vì thế nếu cần sử dụng th°
viện đ°ợc cung cấp kèm sẵn ngôn ngữ C thì nên sử dụng
#include để cải thiện tốc đá biên dịch ch°¡ng trình.
#include tệp tin tiêu đề (.h) trong th° mục đặt project. Nếu không
tìm thấy, bá tiền xử lý tìm kiếm tệp tin tiêu đề trong th°
mục chứa tệp tiêu đề của th° viện ngôn ngữ C. Vì thế nếu 11
cần sử dụng th° viện tự viết thì phải sử dụng #include
Biên dịch và chạy ch°¡ng trình bằng 2 dòng lệnh sau: $ gcc main.c hello.c -o hello $ ./hello
Hãy kiểm chứng lại là kết quả hiển thị trên màn hình vẫn giống nh° lần tr°ớc: Hello, I am , Welcome to IT007! 3.3.3 Makefile
Nếu chúng ta th°ßng xuyên chèn thêm tệp vào project hay cần
thay đổi các tham số biên dịch thì việc biên dịch và chạy ch°¡ng
trình bằng cách sử dụng 2 dòng lệnh trên trá nên dài dòng, dễ xảy
ra lßi và rất khó để sửa lại câu lệnh bằng tay. Để khắc phục tình
trạng này, mát ch°¡ng trình có tên là make đã đ°ợc ra đßi để tự
đáng hóa các thao tác có tính lặp đi lặp lại. Mát điều may mắn là
make đã đ°ợc cài tự đáng cùng với gói build-essential khi chúng ta cài đặt gcc. 12
Mặc định, make sẽ thực thi mát tệp tin là Makefile trong th°
mục hiện hành gọi make, vì thế hãy sử dụng vim để soạn thảo tệp
Makefile nằm trong th° mục project với nái dung sau (chú ý sau
khi nhấn 8:9 xuống dòng thì phải bắt đầu bằng 1 dấu TAB): all: hello run hello: gcc main.c hello.c -o hello run: ./hello clean: rm -f hello
Bây giß biên dịch và chạy ch°¡ng trình chỉ cần sử dụng câu lệnh: $ make all
Makefile bao gồm các target (những gì muốn thực hiện).
Makefile á trên có 4 target là all, hello, run, và clean. Sau dấu 8:9 13
của all có hello và run, nghĩa là all phụ thuác hello và run, khi
thực thi all thì sẽ chuyển thành thực thi hello và run tr°ớc sau đó
mới quay lại thực thi all. Nếu chạy make không có tham số thì
target đầu tiên sẽ đ°ợc thực thi. Các target trong Makefile thực
chất là tên các tệp tin. Nếu chạy make all lại mát lần nữa thì target
hello sẽ không đ°ợc thực thi do tệp tin hello đã tồn tại trong hệ
thống, target hello sẽ đ°ợc thực thi lại nếu mát trong các phụ
thuác của nó là hello.c và main.c thay đổi, điều này giúp giảm rất
nhiều thßi gian nếu project có nhiều tệp tin không cần phải thay
đổi nái dung tr°ớc mßi lần biên dịch. Cũng chính vì lý do này, nên
để biên dịch chính xác, thì trong th° mục hiện tại không đ°ợc
chứa các tệp tin có tên all, run, hay clean. Ng°ợc lại, nếu vẫn
muốn tồn tại các tệp tin nói trên thì phải thêm .PHONY:
vào cuối Makefile để ép buác make luôn thực thi . all: hello run hello: gcc main.c hello.c -o hello run: ./hello 14 clean: rm -f hello .PHONY: hello 3.3.4 Trình gỡ lßi
Trình gỡ lßi là công cụ hß trợ tìm kiếm các nguy c¡ tiềm tàng
hoặc các vấn đề khiến ch°¡ng trình chạy không nh° mong muốn.
Việc kiểm soát lßi và nhiều dòng code là mát việc khó khăn đối
với ng°ßi viết ch°¡ng trình, vì thế việc rà soát lßi để tiến hành
điều chỉnh lại cần sự trợ giúp đắc lực từ trình gỡ lßi. Trong bài
thực hành này gdb đ°ợc sử dụng làm công cụ thực hành.
Sử dụng vim để viết ch°¡ng trình tính giai thừa factorial.c nh° sau:
/*######################################
# University of Information Technology # # IT007 Operating System # # , # # File: factorial.c #
######################################*/ 15 #include int main() { int i, num, j;
printf("Enter the number: "); scanf ("%d", &num ); for (i=1; i j=j*i;
printf("The factorial of %d is %d\n", num, j); return 0; }
Biên dịch và chạy ch°¡ng trình trên. Kết quả của ch°¡ng
trình SAI phải không? Để thu thập thông tin gỡ lßi mát ch°¡ng
trình thì trong khi biên dịch, thêm tùy chọn -g vào tr°ớc tệp mã nguồn nh° sau:
$ gcc -g factorial.c -o factorial 16
Chạy gdb để gỡ lßi ch°¡ng trình bằng câu lệnh sau: $ gdb factorial
Tạo mát breakpoint trong ch°¡ng trình bằng break dừng>, chẳng hạn: (gdb) break 10
Nếu project có nhiều tệp thì sử dụng cú pháp: break
. Hoặc thậm chí có thể tạo breakpoint ngay tại
mát hàm bằng cú pháp: break .
Sau khi đặt breakpoint, trong lúc thực thi ch°¡ng trình, dgb sẽ
dừng tại breakpoint và đ°a ra nhắc lệnh để gỡ lßi. Để tiếp tục thực
thi ch°¡ng trình, chạy câu lệnh sau: (gdb) run
Sau khi sử dụng lệnh run, gdb có thể sẽ thông báo nh° sau:
Breakpoint 1, main () at factorial.c:10 10 j=j*i; 17