intTypePromotion=1
zunia.vn Tuyển sinh 2024 dành cho Gen-Z zunia.vn zunia.vn
ADSENSE

Các nội dung cần ôn tập với C

Chia sẻ: Amry Hellmaster | Ngày: | Loại File: PDF | Số trang:44

106
lượt xem
18
download
 
  Download Vui lòng tải xuống để xem tài liệu đầy đủ

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...

Chủ đề:
Lưu

Nội dung Text: Các nội dung cần ôn tập với C

  1. 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: #include int getopt(int argc, char *const argv[], const char *optstring); extern char *optarg; extern int optind, opterr, optopt; • 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: extern char **environ; char *getenv(const char *name); int putenv(const char *string); 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: $ ./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 Hãy viết chương trình minh họa để ra kết quả như trên. #include #include 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
  2. 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 #include 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 #include #include 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
  3. 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: #include 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 truy cập đến thuộc tính của file 3/44
  4. #include 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 */ }; Các hàm làm việc với thuộc tính của file : 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); 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
  5. 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); Các hàm làm việc với File trong thư viện chuẩn: #include 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); 5/44
  6. 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 #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 \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
  7. 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 #include #include #include #include #include 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
  8. } 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 #include #include 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 #include #include #include #include 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 #include #include #include 8/44
  9. #include 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 #include #include #include 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
  10. { 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 ",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 #include #include #include void main(int argc, char* argv[]) { char* file_path; char* dir_path; char* p_slash; if (argc != 2 || !argv[1]) { fprintf(stderr, "Usage: %s \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
  11. exit(1); } p_slash = file_path; while ( (p_slash = strchr(p_slash, '/')) != NULL) { strncpy(dir_path, file_path, p_slash-file_path+1); dir_path[p_slash-file_path+1] = '\0'; if (access(dir_path, F_OK) == -1) { printf("%s: Directory '%s' in the path does not exist.\n","ACCESS DENIED", dir_path); exit(2); } if (access(dir_path, X_OK) == -1) { printf("%s: Directory '%s' in the path – no 'X' permission.\n","ACCESS DENIED", dir_path); exit(2); } p_slash++; } if (access(file_path, F_OK) == -1) { printf("%s: File does not exist.\n", "ACCESS DENIED"); exit(2); } if (access(file_path, R_OK) == -1) { printf("%s: no read access to file.\n", "ACCESS DENIED"); exit(2); } printf("Permission OK\n"); } #include #include #include #include int main(int argc,char *argv[]) { if (argc < 2) { printf("\n Usage: %s ",argv[0]); return 1; } if (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
  12. 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 file argv[1] strncpy(buf,argv[1],len); //strcpy(parent,buf); while (len !=0) { stat(buf,&statbuf); if (! (statbuf.st_mode & S_IREAD) ) { strcpy(parent,buf); //luu thu muc gay loi reason = 0; //khong co quyen doc } else if (! (statbuf.st_mode & S_IEXEC)) { strcpy(parent,buf); //luu thu muc gay loi reason = 1; //khong co quyen thuc thi } ptr = strrchr(buf,'/'); len= ptr - buf; //lay thu muc cha cua buf strncpy(buf,buf,len); } if (reason) { printf("\n 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 thực hiện có nằm ở một trong các đường dẫn trong PATH không. Hãy viết chương trình minh họa công việc này. #include #include #include #include #include #include int main(int argc,char *argv[]) { char path[256], *ptr, *buf; int len = 0; if (argc < 2) { printf("\n Usage: %s ",argv[0]); return 1; } // kiem tra su ton tai (duong dan tuong doi hoac tuyet doi) if (access(argv[1],F_OK)==0) { printf("\n File exists"); 12/44
  13. return 0; } // neu khong ton tai thi tim kiem trong bien moi truong PATH buf = (char * ) malloc (256); strcpy(buf, getenv("PATH")); // chen them dau : vao cuoi buf cho de xu li strcat(buf,":"); ptr = strchr(buf,':'); while (ptr!=NULL) { len = ptr - buf; //lay path dau tien ke tu vi tri buf strncpy(path,buf,len); strcat(path,"/"); 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 tiến trình: Xác định định danh tiến trình: pid_t getpid(void); pid_t getppid(void); uid_t getuid(void); uid_t geteuid(void); gid_t getgid(void); gid_t getegid(void); Tạo các tiến trình con: int system (const char *string); pid_t fork(void); pid_t wait(int *statloc); pid_t waitpid(pid_t pid, int *statloc, int options); int execl(const char *path, const char *arg0, ..., (char *)0); int execlp(const char *file, const char *arg0, ..., (char *)0); int execle(const char *path, const char *arg0, ..., (char *)0, const char *envp[]); int execv(const char *path, const char *argv[]); int execvp(const char *file, const char *argv[]); int 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
  14. 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 tiến trình cha và tiến trình con. (PID,PPID, UID, EUID, GID, EGID). #include #include #include int main(int argc,char *argv[]) { pid_t child_pid; child_pid = Fork(); switch(child_pid) { case -1: perror("Fork fail:"); return 1; case 0: // tien trinh con printf("\n child: %d %d %d %d %d %d", getpid(),getppid(),getuid(),geteuid(),getgid(),getegid()); break; default: // 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 = fork(); // tach tien trinh B tu A switch (pB) { Case -1: break; Case 0: pC=fork();// sinh C tu B Switch(pC) { Case -1 : break; Case 0 : pD= fork();//sinh D tu C Break; Default : break; } 14/44
  15. Default : break; } } //b Int main() { Pid_t pA, pB,pC,pD; pB=fork(); //sinh B tu A switch (pB) { Case -1: break; Case 0: break; Default: pC=fork(); //sinh C tu A pD= fork(); // sinh D tu A } } //c Int main() { Pid_t p1, p2a, p2b, p3a, p3b, p3c, p3d; P1 = fork() ; // sinh 1 tu 0 Switch(p1) { Case -1: break; Case 0: p3d= fork(); //sinh 3d tu 1 P2b= fork(); //sinh 2b tu 1 If (p2b = = 0) P3c = fork(); // sinh 3c tu 2b Default : p3b = fork(); //sinh 3b tu 0 P2a = fork(); //sinh 2a tu 0 If (p2a = = 0) p3a = fork(); //sinh 3a tu 2a } } 13. Viết chương trình mô phỏng hàm SYSTEM bằng cách sử dụng các hàm FORK và EXEC. #include #include #include #include int main(){ pid_t child_id; printf("Statrting process \n"); child_id=fork(); switch (child_id) { case -1: printf("fork error"); break; case 0: execlp("ps","ps","-af",0); default: wait(0); printf("from parent: child finished \n"); } 15/44
  16. return 0; } 14. Viết chương trình minh họa công việc chuyển hướng vào ra. Ví dụ như: Đọc dữ liệu từ file /etc/passwd sau đó sắp xếp các hàng theo cột tên ngừơi dùng (cột thứ nhất). #include #include int main(int argc, char *argv[]) { char *filename; if(argc != 2) { fprintf(stderr, "usage: useupper file\n"); exit(1); } filename = argv[1]; if(!freopen(filename, "r", stdin)) { fprintf(stderr, "could not redirect stdin to file %s\n", filename); exit(2); } execlp("sort", "sort", "+0" , "-1" , 0); fprintf(stderr, "could not exec sort!\n"); exit(3); } SIGNAL. Cơ chế liên lạc thông qua Signal. Các hàm hệ thống sau được sử dụng: #include void (*signal(int sig, void (*func)(int)))(int); #define SIG_ERR (void (*)())-1 ; #define SIG_DFL (void (*)()) 0; #define SIG_IGN (void (*)())1 int kill(pid_t pid, int sig); unsigned int alarm(unsigned int seconds); int pause(void); int sigaction(int sig, const struct sigaction *act, struct sigaction *oact); struct sigaction { void (*sa_handler)(int); /* addr of signal handler, */ sigset_t sa_mask; /* additional signals to block */ int sa_flags; /* signal options*/ void (*sa_sigaction)(int, siginfo_t *, void *); }; 16/44
  17. int sigaddset(sigset_t *set, int signo); int sigemptyset(sigset_t *set); int sigfillset(sigset_t *set); int sigdelset(sigset_t *set, int signo); int sigismember(sigset_t *set, int signo); int sigpending(sigset_t *set); int 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); } int main(int 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 answer[30]; printf("\nRealy Exit? [y/N]: "); fflush(stdout); gets(answer); if (answer[0] == 'y' || answer[0] == 'Y') { 17/44
  18. printf("\nExiting...\n"); fflush(stdout); exit(0); } else { printf("\nContinuing\n"); fflush(stdout); ctrl_c_count = 0; } } sigprocmask(SIG_SETMASK, &old_set, NULL); } void catch_suspend(int sig_num) { sigset_t mask_set; sigset_t old_set; signal(SIGTSTP, catch_suspend); sigfillset(&mask_set); sigprocmask(SIG_SETMASK, &mask_set, &old_set); printf("\n\nSo far, '%d' Ctrl-C presses were counted\n\n", ctrl_c_count); fflush(stdout); sigprocmask(SIG_SETMASK, &old_set, NULL); } int main() { 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. b. Một Signal khác bị bắt bởi tiến trình và hàm thực hiện Signal handler trả lại kết quả. (Bài này có tính minh họa để các bạn hiểu hơn về cách sử dụng) 18/44
  19. static void sig_alrm(int signo) { /* nothing to do, just returning wakes up sigsuspend() */ } unsigned int sleep(unsigned int nsecs) { struct sigaction newact, oldact; sigset_t newmask, oldmask, suspmask; unsigned int unslept; /* set our handler, save previous information */ newact.sa_handler = sig_alrm; sigemptyset(&newact.sa_mask); newact.sa_flags = 0; sigaction(SIGALRM, &newact, &oldact); /* block SIGALRM and save current signal mask */ sigemptyset(&newmask); sigaddset(&newmask, SIGALRM); sigprocmask(SIG_BLOCK, &newmask, &oldmask); alarm(nsecs);  sử dụng hàm ALARM và SIGALRM để xây dựng SLEEP suspmask = oldmask; sigdelset(&suspmask, SIGALRM); /* make sure SIGALRM isn't blocked */ sigsuspend(&suspmask); /* wait for any signal to be caught */ /* some signal has been caught, SIGALRM is now blocked */ unslept = alarm(0); sigaction(SIGALRM, &oldact, NULL); /* reset previous action */ /* reset signal mask, which unblocks SIGALRM */ sigprocmask(SIG_SETMASK, &oldmask, NULL); return(unslept); } PIPE và FIFO Để sử dụng kết quả của tiến trình này là đầu vào của tiến trình khác thì ngừoi ta dùng PIPE hay 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
  20. 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ụ sau minh họa cho cách làm việc: int main() { FILE *read_fp; char buffer[BUFSIZ + 1]; int chars_read; memset(buffer, '\0', sizeof(buffer)); read_fp = popen("ps -ax", "r"); if (read_fp != NULL) { chars_read = fread(buffer, sizeof(char), BUFSIZ, read_fp); while (chars_read > 0) { buffer[chars_read - 1] = '\0'; printf("Reading:-\n %s\n", buffer); chars_read = fread(buffer, sizeof(char), BUFSIZ, read_fp); } pclose(read_fp); exit(0); } exit(0); } int pipe(int file_descriptor[2]); int mkfifo(const char *filename, mode_t mode); int mknod(const char *filename, mode_t mode | S_IFIFO, (dev_t) 0); key_t ftok ( char *pathname, char proj ); Trong phần này chúng ta có 1 số bài tập như sau: 17. Viết chương trình minh họa chuyển đổi định hướng giữa 2 tiến trình cha và con sao cho đầu ra chuẩn của tiến trình này là đầu vào chuẩn của tiến trình kia. #include #include void do_child(int data_pipe[]) { int c; int rc; close(data_pipe[1]); while ((rc = read(data_pipe[0], &c, 1)) > 0) { putchar(c); } exit(0); } void do_parent(int data_pipe[]) { int c; int rc; 20/44
ADSENSE

CÓ THỂ BẠN MUỐN DOWNLOAD

 

Đồng bộ tài khoản
2=>2