Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 44 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
44
Dung lượng
236,75 KB
Nội dung
Các nội dung cần ôn tập với C Kiến thức chung Kiến thức lập trình C trong UNIX về cơ bản cũng giống như học lập trình trong Borland C 3.1 (còn gọi là phiên bản BC cho DOS) cho nên các bạn có thể tham khảo các cú pháp cũng như các hàm trong BC. Tuy nhiên chúng ta cũng cần nhấn mạnh 1 chút về các vấn đề sau: • Program Arguments. int main(int argc, char *argv[]) . o Chú ý rằng argv[0] luôn có và chính là tên chương trình. o Để lấy các tham số và các đối số một cách đầy đủ thì cần dùng các hàm và biến môi trường như sau: • Environment Variables. Liệt kê hoặc thiết lập các biến môi trường thông qua các hàm và biến toàn cục như sau: Có 1 số bài tập như sau: 1. Giả sử có 1 chương trình cần chạy với 1 số options như -i, -l, -r, -f và sau -f sẽ có 1 argument. Khi đó chương trình chạy như sau: Hãy viết chương trình minh họa để ra kết quả như trên. #include <stdio.h> #include <unistd.h> int main(int argc, char *argv[]) { int opt; while((opt = getopt(argc, argv, "if:lr")) != -1) { switch(opt) { case 'i': case 'l': case 'r': printf("option: %c\n", opt); break; 1/44 #include <unistd.h> int getopt(int argc, char *const argv[], const char *optstring); extern char *optarg; extern int optind, opterr, optopt; extern char **environ; char *getenv(const char *name); int putenv(const char *string); $ ./argopt -i -lr 'hi there' -f fred.c -q option: i option: l option: r option: f filename: fred.c argopt: invalid option q unknown option: q argument: hi there case 'f': printf("filename: %s\n", optarg); break; case ':': printf("option needs a value\n"); break; case '?': printf("unknown option: %c\n", optopt); break; } } for(; optind < argc; optind++) printf("argument: %s\n", argv[optind]); return(0); } 2. Hãy viết chương trình làm việc với biến môi trường như sau: a. Liệt kê các biến môi trường của tiến trình hiện tại thông qua biến toàn cục environ. #include <stdlib.h> #include <stdio.h> int main() { char **env = environ; while(*env) { printf("%s\n",*env); env++; } return(0); } b. Lấy thông tin của biến môi trường thông qua hàm getenv. Ví dụ như các biến PATH, HOME,… #include <stdlib.h> #include <stdio.h> #include <string.h> int main(int argc, char *argv[]) { char *var, *value; if(argc == 1 || argc > 3) { fprintf(stderr,"usage: environ var [value]\n"); exit(1); } var = argv[1]; value = getenv(var); if(value) printf("Variable %s has value %s\n", var, value); else printf("Variable %s has no value\n", var); if(argc == 3) { char *string; value = argv[2]; 2/44 string = malloc(strlen(var)+strlen(value)+2); if(!string) { fprintf(stderr,"out of memory\n"); exit(1); } strcpy(string,var); strcat(string,"="); strcat(string,value); printf("Calling putenv with: %s\n",string); if(putenv(string) != 0) { fprintf(stderr,"putenv failed\n"); free(string); exit(1); } value = getenv(var); if(value) printf("New value of %s is %s\n", var, value); else printf("New value of %s is null??\n", var); } return(0); } Làm việc với File Có hai cơ chế làm việc với File. • Truy cập và thao tác với File thông qua các lời gọi hệ thống. File Descriptor chuẩn: STDIN_FILENO, STDOUT_FILENO, và STDERR_FILENO • Truy cập và thao tác với File thông qua các hàm chuẩn thư viện. con trỏ chuẩn kiểu FILE như: FILE * stdin, stdout, stderr. Các hàm làm việc ở mức thấp – mức lời gọi hệ thống truy cập đến nội dung file: Các hàm truy cập đến thuộc tính của file 3/44 #include <unistd.h> int creat(const char *pathname, mode_t mode); int open(const char *pathname, int oflag, mode_t mode); int close(int filedes); off_t seek(int filedes, off_t offset, int whence); ssize_t read(int filedes, void *buf, size_t nbytes); ssize_t write(int filedes, const void *buf, size_t nbytes); int dup(int filedes); int dup2(int filedes, int filedes2); Các hàm làm việc với thuộc tính của file : Thư mục cũng là 1 kiểu File đặc biệt trong Unix. Để truy cập thư mục Unix cung cấp các lời gọi hệ thống và cấu trúc như sau: 4/44 #include <sys/stat.h> int stat(const char *restrict pathname, struct stat *restrict buf); int fstat(int filedes, struct stat *buf); struct stat { mode_t st_mode; /* file type & mode (permissions) */ ino_t st_ino; /* i-node number (serial number) */ dev_t st_dev; /* device number (file system) */ dev_t st_rdev; /* device number for special files */ nlink_t st_nlink; /* number of links */ uid_t st_uid; /* user ID of owner */ gid_t st_gid; /* group ID of owner */ off_t st_size; /* size in bytes, for regular files */ time_t st_atime; /* time of last access */ time_t st_mtime; /* time of last modification */ time_t st_ctime; /* time of last file status change */ blksize_t st_blksize; /* best I/O block size */ blkcnt_t st_blocks; /* number of disk blocks allocated */ }; int access(const char *pathname, int mode); int chmod(const char *pathname, mode_t mode); int fchmod(int filedes, mode_t mode); int chown(const char *pathname, uid_t owner, gid_t group); int fchown(int filedes, uid_t owner, gid_t group); int link(const char *existingpath, const char *newpath); int unlink(const char *pathname); int remove(const char *pathname); int rename(const char *oldname, const char *newname); int symlink(const char *actualpath, const char *sympath); ssize_t readlink(const char* restrict pathname, char *restrict buf,size_t bufsize); Các hàm làm việc với File trong thư viện chuẩn: 5/44 int mkdir(const char *pathname, mode_t mode); int rmdir(const char *pathname); struct dirent { ino_t d_ino; /* i-node number */ char d_name[NAME_MAX + 1]; /* null-terminated filename */ } DIR *opendir(const char *pathname); struct dirent *readdir(DIR *dp); void rewinddir(DIR *dp); int closedir(DIR *dp); long telldir(DIR *dp); void seekdir(DIR *dp, long loc); int chdir(const char *pathname); int fchdir(int filedes); char *getcwd(char *buf, size_t size); #include <stdio.h> FILE *fopen(const char *filename, const char *mode); size_t fread(void *ptr, size_t size, size_t nitems, FILE *stream); size_t fwrite (const void *ptr, size_t size, size_t nitems, FILE *stream); int fclose(FILE *stream); int fflush(FILE *stream); int fseek(FILE *stream, long int offset, int whence); int fgetc(FILE *stream); int getc(FILE *stream); int getchar(); int fputc(int c, FILE *stream); int putc(int c, FILE *stream); int putchar(int c); char *fgets(char *s, int n, FILE *stream); char *gets(char *s); int printf(const char *format, ); int sprintf(char *s, const char *format, ); int fprintf(FILE *stream, const char *format, ); int scanf(const char *format, ); int fscanf(FILE *stream, const char *format, ); int sscanf(const char *s, const char *format, ); int ferror(FILE *stream); int feof(FILE *stream); void clearerr(FILE *stream); int fileno(FILE *stream); FILE *fdopen(int fildes, const char *mode); Với các hàm như vậy chúng ta có 1 số bài tập mẫu như sau: 3. Viết chương trình mô phỏng các lệnh cp, rm, mv trong Unix (sử dụng các lời gọi hệ thống hoặc các hàm thư viện). Lệnh copy: #include <stdio.h> #define MAX_LINE_LEN 1000 void main(int argc, char* argv[]) { char* file_path_from; /* source path */ char* file_path_to; /* target path */ FILE* f_from; /* source stream */ FILE* f_to; /* target stream */ char buf[MAX_LINE_LEN+1]; if (argc != 3 || !argv[1] || !argv[2]) { fprintf(stderr, "Usage: %s <source file path> <target file path>\n",argv[0]); exit(1); } file_path_from = argv[1]; file_path_to = argv[2]; f_from = fopen(file_path_from, "r"); if (!f_from) { fprintf(stderr, "Cannot open source file: "); perror(""); exit(1); } f_to = fopen(file_path_to, "w+"); if (!f_from) { fprintf(stderr, "Cannot open target file: "); perror(""); exit(1); } while (fgets(buf, MAX_LINE_LEN+1, f_from)) { if (fputs(buf, f_to) == EOF) { fprintf(stderr, "Error writing to target file: "); perror(""); exit(1); } } if (!feof(f_from)) { fprintf(stderr, "Error reading from source file: "); perror(""); exit(1); } if (fclose(f_from) == EOF) { fprintf(stderr, "Error when closing source file: "); perror(""); } if (fclose(f_to) == EOF) { fprintf(stderr, "Error when closing target file: "); perror(""); } } 6/44 4. Xác định thuộc tính của các file, mô phỏng công việc như khi chạy: $ ls –l file_name. #include <sys/stat.h> #include <stdio.h> #include <time.h> #include <io.h> #include <sys/types.h> #include <fcntl.h> int main(int argc, char * argv[]) { struct stat statbuf; int stream; char mode[20]="-rwxrwxrwx"; char output[200]=""; char temp[20]=""; if (argc==1) { printf("Usage: %s <file_n return 1; } if ((stream = _open(argv[1], _O { perror("Error:"); return 1; } fstat(stream, &statbuf); close(stream); // Kiem tra quyen if (!S_IRUSR(statbuf.st_mode)) mode[1]='-'; if (!S_IWUSR(statbuf.st_mode)) mode[2]='-'; if (!S_IXUSR(statbuf.st_mode)) mode[3]='-'; if (!S_IRGRP(statbuf.st_mode)) mode[4]='-'; if (!S_IWGRP(statbuf.st_mode)) mode[5]='-'; if (!S_IXGRP(statbuf.st_mode)) mode[6]='-'; if (!S_IROTH(statbuf.st_mode)) mode[7]='-'; if (!S_IWOTH(statbuf.st_mode)) mode[8]='-'; if (!S_IXOTH(statbuf.st_mode)) mode[9]='-'; // kiem tra loai file if (S_ISLNK(statbuf.st_mode)) mode[0]='l'; else if (S_ISCHR(statbuf.st_mode)) mode[0]='c'; else if (S_ISBLK(statbuf.st_mode)) mode[0]='b'; else if (S_ISSOCK(statbuf.st_mode)) mode[0]='s'; else if (S_ISFIFO(statbuf.st_mode)) mode[0]='p'; strcat(output,mode); sprintf(temp," %s ",ctime(&statbuf.st_ctime)); strcat(output,temp); strcat(output," "); strcat(output,argv[0]); return 0; 7/44 } 5. Mô phỏng chương trình thay đổi sở hữu hay quyền truy cập như: chmod, chown, chgrp. 6. Sử dụng các hàm dup, dup2 để thay đổi hướng vào ra dữ liệu. Ví dụ khi thực hiện hàm printf thì kết quả không phải hiện ra màn hình mà ghi vào file nào đó. #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> int main(int argc, char **argv) { int fd = open(argv[1], O_CREAT | O_WRONLY); //luu stdout int oldstdout = dup(1); //chuyen huong dup2(fd, 1); close(fd); //in ra file thay vi stdout: printf("test"); //khoi phuc stdout dup2(oldstdout, 1); close(oldstdout); return 0; } 7. Chúng ta có 2 kiểu tạo file liên kết (LINK). Hãy dùng các hàm liên quan để đọc nội dung các file liên kết đó. Chú ý với file liên kết mềm. #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <sys/types.h> #include <stdio.h> int main(int argc,char *argv[]) { int fd = open(argv[1], O_RDONLY); struct stat statbuf; char buf[256]; fstat(fd, &statbuf); if (S_ISLNK(statbuf.st_mode)) { // doc ten file chua trong file lien ket mem nay read(fd,buf,200); close(fd); fd = open(buf,O_RDONLY); printf(“\n %s is symbolic link to %s”, argv[1],buf); } while (read(fd,buf,256)) printf(“%s”,buf); close(fd); return 0; } 8. Viết chương trình đọc nội dung của thư mục, liệt kê các file và thư mục con của nó theo dạng cây thư mục với mức độ sâu cho trước. Ví dụ: nếu liệt kê thư mục TEMP với độ sâu là 2 thì ta liệt kê các file, thư mục trong thư mục TEMP và các file và thư mục trong các thư mục con của thư mục TEMP. #include <unistd.h> #include <stdio.h> #include <dirent.h> #include <string.h> 8/44 #include <sys/stat.h> void printdir(char *dir, int depth) { DIR *dp; struct dirent *entry; struct stat statbuf; if((dp = opendir(dir)) == NULL) { fprintf(stderr,"cannot open directory: %s\n", dir); return; } chdir(dir); while((entry = readdir(dp)) != NULL) { stat(entry->d_name,&statbuf); if(S_ISDIR(statbuf.st_mode)) { if(strcmp(".",entry->d_name) == 0 || strcmp(" ",entry->d_name) == 0) continue; printf("%*s%s/\n",depth,"",entry->d_name); printdir(entry->d_name,depth+4); } else printf("%*s%s\n",depth,"",entry->d_name); } chdir(" "); closedir(dp); } int main() { printf("Directory scan of /home:\n"); printdir("/home",0); printf("done.\n"); exit(0); } #include <sys\stat.h> #include <fcntl.h> #include <unistd.h> #include <dirent.h> void printdir(char *dir,int maxdepth) { static int depth = 0; Dir *dp; struct dirent *entry; struct stat statbuf; if ((dp= opendir(dir))==NULL) { perror("open:"); return; } chdir(dir); // tang do sau depth ++; while ((entry= readdir(dp))!=NULL) { stat(entry->d_name,&statbuf); if (S_ISDIR(statbuf.st_mode)) 9/44 { if ((strcmp(".",entry->d_name)==0) || strcmp(" ",entry->d_name) ==0) { continue; } printf("%s/\n",entry->d_name); // neu dat do sau lon nhat thi dung de qui if (depth < maxdepth) { printdir(entry->d_name,maxdepth); } } else { // in ten file printf("\t%s",entry->d_name); } } closedir(dp); } int main(int argc,char *argv[]) { if (argc < 3) { printf("\n Usage: %s <dir_name> <max_depth>",argv[0]); return 1; } int maxdepth = atoi(argv[2]); printdir(argv[1],maxdepth); printf("\n done! \n"); return 0; } 9. Giả sử có 1 file với đường dẫn đầy đủ, hãy xác định quyền được đọc của file. Nếu file không có quyền được đọc đối với người dùng hiện tại, hãy xác định xem nguyên nhân bắt nguồn từ đâu (do thư mục cha,ông nào cuả nó không cho quyền đọc hay thực hiện). Cũng làm công việc như trên nhưng với đường dẫn bất kỳ, có thể là tuyệt đối ,có thể là tương đối. #include <stdio.h> #include <unistd.h> #include <string.h> #include <malloc.h> void main(int argc, char* argv[]) { char* file_path; char* dir_path; char* p_slash; if (argc != 2 || !argv[1]) { fprintf(stderr, "Usage: %s <full file path>\n", argv[0]); exit(1); } file_path = argv[1]; dir_path = (char*)malloc(strlen(file_path)+1); if (!dir_path) { fprintf(stderr, "out of memory\n"); 10/44 [...]... *file, const char *arg0, , (char *)0); execle(const char *path, const char *arg0, , (char *)0, const char *envp[]); execv(const char *path, const char *argv[]); execvp(const char *file, const char *argv[]); execve(const char *path, const char *argv[], const char *envp[]); Với c c hàm này, chúng ta c 1 số bài tập đơn giản như sau: 13/44 11 Tạo 1 tiến trình con bằng hàm FORK và x c định c c thông tin c a... FIFO Trong Unix c 1 số hàm làm vi c như sau: #include FILE *popen(const char *command, const char *open_mode); int pclose(FILE *stream_to_close); 19/44 Hàm popen cho phép tiến trình đang chạy gọi 1 chương trình kh c chạy (sinh ra 1 tiến trình con) sau đó sẽ th c hiện vi c lấy ho c truyền dữ liệu cho tiến trình mới Tiến trình mới đư c gọi với tên chương trình chạy là const char *command Ví dụ... argc,char *argv[]) { signal(SIGINT,catch); while (1) ; //khong lam j return 0; } #include #include #include int ctrl _c_ count = 0; #define CTRL _C_ MAX 5 void catch_int(int sig_num) { sigset_t mask_set; sigset_t old_set; signal(SIGINT, catch_int); sigfillset(&mask_set); sigprocmask(SIG_SETMASK, &mask_set, &old_set); ctrl _c_ count++; if (ctrl _c_ count >= CTRL _C_ MAX) { char... tien trinh cha printf("\n parent: %d %d %d %d %d %d", getpid(),getppid(),getuid(),geteuid(), getgid(),getegid()); } return 0; } 12 Sử dụng hàm FORK để tạo ra dãy c c tiến trình với quan hệ cha con như sau: a A B C D : t c là A là cha c a B, B là cha c a C, C là cha c a D b A (B, C, D) : t c là A là cha c a B, C, D c Xây dựng c y chu trình như sau: //a Int main() { Pid_t pA, pB, pC,pD; pB =... strcat(path,argv[1]); if (access(path,F_OK)==0) { printf("\n File exists"); return 0; } // khong thay trong path thi tim tiep buf = ptr; ptr = strchr(buf,':'); } // khong tim thay printf("\n File not exists"); return 0; } Làm vi c với tiến trình Khi làm vi c với tiến trình thì trư c tiên ta quan tâm đến c c thông tin về tiến trình c ng như c c c ch tạo ra tiến trình C c lời gọi hệ thống sau làm vi c với. .. sigsuspend(const sigset_t *sigmask); int sigprocmask(int how, const sigset_t *set, sigset_t *oset); Phần này chúng ta c 1 số bài tập như sau: 15 Viết 1 chương trình chặn ngắt SIGINT do nhấn phím Ctrl +C, đồng thời đếm số lần nhấn Ctrl +C khi chương trình chạy #include #include void catch(int signum) { static int count = 1; printf("\n An Ctrl -C lan thu:%d",count++); signal(SIGINT,catch);... (access(argv[1],F_OK)==-1) { printf("\n File doesnot exists"); return 1; } if (access(argv[1],R_OK)==0) { printf("\n file access OK"); return 0; } // tim thu muc cha hoac ong khong cho phep doc hoac thuc thi char buf[100]; char *ptr; char parent[100]; 11/44 int reason=0; int len=0; struct stat statbuf; //lay vi tri cuoi cung cua / ptr = strrchr(argv[1],'/'); len= ptr - argv[1]; //lay thu muc cha cua... signal(SIGINT, catch_int); signal(SIGTSTP, catch_suspend); printf(“Please random press Ctrl -C or Ctrl-Z”); while (1) { sleep(1); } } return 0; 16 Minh họa cho vi c sử dụng c c hàm sigaction và sigprocmask chúng ta xây dựng chương trình mô phỏng hàm sleep với tính năng như sau: Tiến trình gọi hàm Sleep sẽ bị tạm ngưng (block) cho đến khi một trong c c sự kiện sau xảy ra: a Thời gian đặt trong hàm Sleep kết th c. .. Thu muc %s khong co quyen thuc thi",parent); } else printf("\n Thu muc %s khong co quyen doc",parent); return 0; } 10 Trong Unix, khi muốn th c hiện 1 file thì hệ thống sẽ x c định sự tồn tại c a file trư c Sự kiểm tra đó phụ thu c vào đường dẫn c a file C thể là đường dẫn tuyệt đối, tương đối ho c chỉ là 1 tên file c n chạy Trường hợp cuối thì hệ thống xẽ thông qua biến PATH để x c định xem file c n. .. phần này chúng ta c 1 số bài tập như sau: 19 Xây dựng chương trình quản lý Message Queue như: a Tạo, hủy đối tượng Message Queue b Ghi, đ c thông điệp từ hàng đợi c Đ c c c thông tin c a Message Queue như: quyền truy c p, người sử dụng, … 20 Viết 2 chương trình trao đổi dữ liệu với nhau thông qua Message Queue #include #include #include #include #include . C c nội dung c n ôn tập với C Kiến th c chung Kiến th c lập trình C trong UNIX về c bản c ng giống như h c lập trình trong Borland C 3.1 (c n gọi là phiên bản BC cho DOS) cho nên c c bạn c . khảo c c c pháp c ng như c c hàm trong BC. Tuy nhiên chúng ta c ng c n nhấn mạnh 1 chút về c c vấn đề sau: • Program Arguments. int main(int argc, char *argv[]) . o Chú ý rằng argv[0] luôn c . t c với File thông qua c c hàm chuẩn thư viện. con trỏ chuẩn kiểu FILE như: FILE * stdin, stdout, stderr. C c hàm làm vi c ở m c thấp – m c lời gọi hệ thống truy c p đến nội dung file: C c hàm