Hàm hệ thống system được đặt trong thư viện chuẩn của C, cho phép chúng ta gọi bất kỳ một câu lệnh nào của hệ thống Unix.
a. Ví dụ 1
int main() {
printf(``Files in Directory are: n'');
system(``ls -l''); } b. Ví dụ 2 Main() { system(« \
echo –n Thư mục hiện hành :;pwd ;\
echo thay đổi thư mục hiện hành :;cd /usr ;\ echo -n Thư mục hiện hành mới là :;pwd ;\ echo Thông tin về tệp trong thư mục fich:;ls –l > /home/ldhieu/fich ») ;n
}
c. Lưu ý
Hàm hệ thống system vẫn được sử dụng trong nhiều hệ điều hành khác, đặc biệt là các hệ điều hành họ Unix như Linux. Trong Unix khi gọi hàm system hệ thống sẽ tạo ra tiến trình con đảm nhận công việc này. Chúng ta sẽ bàn kỷ hơn về chủ đề này ở phần sau.
4.2.3 Các tham số hàm trong C
a. Cấu trúc
Trong các câu lệnh hệ thống của Unix, hầu hết đều có tham số kèm theo. Những tham số này chúng ta có thể thiết lập trong hàm main. Những tham số
này thường đóng vai trò phụ trong câu lệnh nhằm cụ thể hoá hay hạn chế từng chức năng trong câu lệnh.
Cấu trúc : Lenh thamso_1 thamso_2 thamso_n
b. Ví dụ 1
ls –l
Tham số đầu tiên trong hàm main tương ứng với tên lệnh, trong ví dụ trên là ls. Những tham số tiếp theo tương ứng với các đối số và tuỳ chọn được trình bày trong câu lệnh.
c. Ví dụ 2
int main( thamso 1, thamso2) int thamso1 ;
char * thamso2[] ; {
int i, j,k ;
printf(``Nhập hai số tự nhiên »); scanf(«%d %d «,&i,&j ) ; switch(*thamso2[1]) {case ‘d’ : k=i/j ; break ; case ‘m’ : k=i * j ; break ; default :
printf(``Không có thao tác nào thực hiện»); exit() ; } printf(« %d\n«,k ) return 0; }
Chúng ta lưu chương trình này dưới tên tệp prog.c, sau đó thực hiện biên dịch.
$cc prog.c $a.out Nhập hai số tự nhiên : 67 15 4 $ d. Hàm main
Cấu trúc của hàm main đầy đủ được viết như sau :
int main (int argc, char**argv)
Trong đó :
int argc : Số lượng các đối số trong chương trình.
char** argv : Bảng chuổi kí tự chứa các tham số.
Mỗi thành phần của bảng có kiểu con trỏ chỉ đến một đối tượng có kiểu char. Thành phần cuối cùng của bảng tương ứng với con trỏ null
argv[0] : Con trỏ chỉ đến câu lệnh.
argv[1] : Con trỏ chỉ đến tham số đầu tiên. argv[2] : Con trỏ chỉ đến tham số thứ 2. ----
argv[argc] : Con trỏ chỉ đến null.
e. Ví dụ 3 ls -l -t -R /usr/local/cours/ argc = 5 argv = “ls”, “-l”, “-t”, “-R”, “/usr/local/cours/” f. Ví dụ 4 Main() { int argc ; char *argv[] ; { puts(*++argv) ; return 0 ;} }
Nếu tệp được đặt tên coco.c, chúng ta sẽ có kết quả sau :
$cc –o coco coco.c $coco helolo
helolo
g. Ví dụ 5
#include <unistd.h>
int main (int argc, char **argv) { int c, argument_entier;
while ((c = getopt(argc, argv, "a:h")) != EOF) { extern char *optarg;
switch (c) { case 'a':
argument_entier = atoi (optarg); break; case 'h': Affiche_Aide () exit (0); break; } }
extern int optind; char *filename = NULL; if (optind<argc)
filename = argv[optind];
4.2.4 Những lệnh gọi hệ thống
Những lệnh gọi hệ thống là những câu lệnh can thiệp trực tiếp tới lõi thông qua ngôn ngữ C. Đối với việc thiết lập một số thành phần bổ sung khác chúng ta có
thể sử dụng ngôn ngữ khác như FORTRAN, tuy nhiên đây không phải là ngôn ngữ chuẩn của Unix.
Thông thường có 3 loại lệnh gọi hệ thống tương ứng với 3 chức năng chính của lõi.
- Lệnh gọi liên quan đến xuất/nhập ở mức thấp.
- Lệnh gọi quản lý bộ xử lý (tiến trình).
- Lệnh gọi quản lý tệp.
4.2.5 Dò lỗi
Trong thư viện hệ thống UNIX cung cấp nhiều hàm cho phép dò lỗi bằng cách trả về giá trị lỗi tương ứng, thông thường đó là giá trị -1. Những thông tin này được tìm thấy trong biến errono trong thư viện chuẩn C.
4.2.6 Biến errno
Trong trường hợp lỗi, biến này sẽ khởi tạo với một giá trị tương ứng với mã code (mã lỗi) , được đính kèm ở phần dưới.
a. Ví dụ #include<stdio.h> #include<math.h> { float y= -2.3, res ; res=log(y) ; printf(«log : %d|n« , errno) ; }
Lưu với tên tệp prog_erro.c ta sẽ có kết quả sau :
$cc prog_erro.c –lm $a.out
log : DOMIAN error log :33
$
b. Lưu ý
- Để sử dụng biến errno cần thiết phải khai báo thư viện <errno.h> - Biến này không chỉ khởi tạo khi có lỗi mà ngay cả trong lệnh gọi
hệ thống.
c. Bảng giá trị các mã lỗi
1 EPERM Không được cấp quyền xử lý
2 ENONET File này đã tồn tại
3 ESRCH Tiến trình này không tồn tại
4 EINTR Tín hiệu đã bị ngắt bởi lời gọi hệ thống 5 EIO Lỗi trong xuất/nhập dữ liệu
7 E2BIG Danh sách tham số quá dài
8 ENOEXEC Định dạng tệp không tương thích
9 EBADF File này không mở được
10 ECHILD Không phải tiến trình con (khi gọi hàm wait) 11 EAGAIN Không thể tạo tiến trình (khi gọi hàm fock)
12 ENOMEN Không đủ khoảng trống bộ nhớ
13 EACCES Không được cấp quyền vào tệp này
14 EFAULT Thiết bị vật lý không tương thích
15 ENOTBLK Không tồn tại chế độ khối (mode bloc), có thể dùng lệnh mount để chữa lỗi.
16 EBUSY Thiết bị hoặc nguồn không hiệu lực
17 EEXIST File không tồn tại, khi dùng lệnh link
18 EXDEV Hai tệp không thể thiết lập link được vi không tương thích thiết bị.
19 ENODEV Thiết bị vật lý không tồn tại (ví dụ khi đọc máy in)
20 ENOTDIR Không tồn tại thư mục trong tham số lời gọi 21 EISDIR Lỗi khi viết dữ liệu (vào thư mục)
22 EINVAL Các tham số của hàm không hợp lệ
23 ENFILE Không thể mở tệp này được(nên mở lại bằng hàm open).
24 EMFILE Mở quá nhiều tệp
25 ENOTTY Thiết bị này không tương thích
26 ETXTBSY Chương trình đang xử lý, không đọc, ghi được.
27 EFBIG Kích thước tệp quá lớn.
28 ENOSPC Khoảng trống đầy, không ghi thêm được nữa. 29 ESPIPE Không thể di chuyển vị trí (dùng trong lệnh
lseek)
30 EROFS Chí cho phép đọc
31 EMLINK Không thể link tệp được vì vượt quá số lượng max (tối đa 1000 link)
32 EPIPE Không có tiến trình nào được đọc
33 EDOM Tham số không hợp lệ
4.2.7 Xuất/nhập ỏ mức thấp
Các lệnh hệ thống về xuất/nhập được gọi chung là lệnh xuất/nhập ở mức thấp. Khác với các lệnh xử lý tệp, những lệnh xuất/nhập mức thấp không cần bộ đệm.
Sau đây là một số ví dụ.
a. Lệnh cat (không có đối số)
Cú pháp : cat
Chức năng : Cho phép nhập dữ liệu từ bàn phím, dữ liệu được gõ vào sẽ xuất hiện trên màn hình giống như lệnh echo.
Chương trình C dưới đây có thể thực hiện lệnh này : #define DIM 1024 main() { char tamp[DIM] ; int k ;
while ((k=read (0, tamp, sizeof(tamp)))>0 write (1, tam,k) ;
exit(0) ; }
Trong chương trình trên sử dụng hàm hệ thống read với 3 tham số. 0 : Chỉ định đây là đơn vị nhập chuẩn (tức bàn phím)
tamp : Đại chỉ vụng bộ nhớ đảo (là một bảng) chứa thông tin đọc vào. K : Số lượng byte được viết.
Hàm read có kiểu int Các giá trị trả về :
-1: Nếu xuất hiện lỗi trong quá trình đọc. 0 : Trong trường hợpkết thúc tệp.
n : Trường hợp thông thường, n chỉ số kí tự được đọc vào. Và hàm hệ thống write với 3 tham số
1 : chỉ định đây là đơn vị xuất chuẩn (tức màn hình
tamp : Đại chỉ vụng bộ nhớ đảo (là một bảng) chứa thông tin ghi vào. Sizeof(tamp) là kích thước, số byte của vùng bộ nhớ thực hiện.
b. Lệnh cat >file
Chức năng : Tạo tệp file và cho phép chỉnh hướng dữ liệu xuất ra tệp file. Dữ liệu phải được nhập từ bàn phím.
Lệnh cat này có thể được thực hiện bởi đoạn chương trình dưới đây :
#include<errno.h> #define SIZE 1024 main() { char buf[SIZE] ; int n, des ;
if ((des = creat(‘fich don’,0750))<0){ printf(« creat : \d »,errno« ) ;
exit(des) ; }
while ((n=read (0, buf, sizeof(buf)))>0 write (des, buf,n) ;
exit(0) ; }
Trong chương trình có sử dụng hàm nguyên thuỷ create cho phép tạo một tệp mới. Hàm này gồm hai tham số, fich don chỉ tên tệp, 0750 chỉ quyền truy cập tệp.