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

Tài liệu Các nội dung cần ôn tập với C: 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 so options như -i, -1, -r, -f và sau -f sẽ có 1 argu...

pdf44 trang | Chia sẻ: Khủng Long | Lượt xem: 852 | Lượt tải: 0download
Bạn đang xem trước 20 trang mẫu tài liệu Các nội dung cần ôn tập với C, để tải tài liệu gốc về máy bạn click vào nút DOWNLOAD ở trên
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 so options như -i, -1, -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: 1 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 iinclude int main(int argc, char *argv[]) { int opt; while((opt = getopt(argc, argv, "if:lr")) != -1) { switch(opt) { case 'i': case '1' : case 'r': printf("option: %c\n", opt); break; 1/44 case 1f': 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 iinclude #include int main(int argc, char *argv[]) { char *var, *value; if (argc == 1 I I 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); Lam viec v<yi File Co hai ca che lam viec voi File. • Truy cap va thao tac vai File thong qua cac loi goi he thong. File Descriptor chuan: STDIN FILENO, STDOUT FILENO, va STDERR FILENO • Truy cap va thao tac voi File thong qua cac ham chuan thu vien. con tro chuan kieu FILE nhu: FILE * stdin, stdout, stderr. Cac ham lam viec cr muc thap - muc loi goi he thong truy cap den noi 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); Cac ham truy cap den thuoc tinh cua file 3/44 #include int stat(const char *restrict pathname, struct stat *restrict buf); int fstat(int filedes, struct stat *buf); struct stat { m od et stm ode; /* 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 stsize; /* size in bytes, for regular files *1 time t st atime; /* time of last access */ time_t stjmtime; /* 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); ssizet 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 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 closcdir(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 thu viện chuấn: #include FILE *fopen(const char *filename, const char *mode); s i ze t fread(void *ptr, size_t size, size_t nitems, FILE *stream); s ize 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 tildes, const char *mode); 5/44 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[l] || !argv[2]) { fprintf(stderr, "Usage: %s \n",argv[0]); exit (1); } file_path_from = argv[l]; 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: $ Is -1 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==l) { printf("Usage: %s <file_n return 1; } if ((stream = _open(argv[1', _0 { perror("Error:"); return 1; } fstat(stream, Sstatbuf); close(stream); II 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] = '1' ; else if (S_ISCHR(statbuf.st_node) ) mode[0]='c'; else if (S_ISBLK(statbuf.st_node)) mode[0]='b'; else if (S_ISSOCK(statbuf.stjnode)) mode[0]='s'; else if (S_ISFIFO(statbuf.st_mode)) mode[0]='p'; strcat(output,mode); sprintf(temp," %s ", ctime(Sstatbuf.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 #include #include int main(int argc, char **argv) { int fd = open(argv[1]/ 0_CREAT I 0_WR0NLY); //luu stdout int oldstdout = dup(l); //chuyen huong dup2(fd, 1); close(fd); //in ra file thaỵ vi stdout: printf("test"); //khoi phuc stdout dup2(oldstdout, 1); close(oldstdout); return 0; 2____________________ ______________ ______________________________________ _____________ 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], 0_RD0NLY); struct stat statbuf; char buf[256]; fstat(fd, Sstatbuf); 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,0_RD0NLY); printf("\n %s is symbolic link to %s", argv[1],buf); } while (read(fd,buf,256)) printf("%s",buf); close(fd); return 0; 2_______________________________________________________________________________________ 8. Viet chương ừì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ư muc con của thư muc TEMP. #include #include #include #include __________________________________________________________ 8/44 #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 aaxdepth) { 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,Sstatbuf); ______ if (S ISDIR(statbuf.st mode)) 9/44 { if ( (strcmp (".",entrv->đ_name)==0) II strcmpC'. . ", entry->d_name) ==0) { continue; } printf ("%s/\n",entry->d_name); II 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 ",argvt0;); 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 finclude finclude #include void main(int arge, char* argv[]) { char* file_path; char* dir_path; char* p_slash; if (arge != 2 || !argv[i;) { fprintf(stderr, "Usage: %s \n", argv[0]); exit (1); } file_path = argv[l]; dir_path = (char*)malloc(strlen(file_path)+1); if (!dir_path) { _______ fprintf(stderr, "out of memory\n");______________________ 10/44 exit (1); p_slash = file_path; while ( (p_slash = strchr(p_slash, '/')) != NULL) { strncpy(dir_path, file_path, p_slash-file_path+l); dir_path[p_slash-file_path+l] = '\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", exit(2); } "ACCESS DENIED"); if (access(file_path, R_OK) == -1) { printf("%s: no read access to file.\n", DENIED"); exit(2); > "ACCESS printf("Permission OK\n"); tinclude #include tinclude #include int main(int argc,char *argv[]) { if (argc < 2) { printf(”\n Usage: %s ",argv[0]); return 1; } if (access(argv[1],F_0K)==-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[l]; //lay thu muc cha cua file argvfl] strncpy(buf,argv[1], len) ; //strcpy(parent,buf); while (len !=0) { stat(buf,Sstatbuf); 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; > II 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 II 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; } II khong thay trong path thi tim tiep buf = ptr; ptr = strchr(buf,':'); } // khong tim thay printf("\n File not exists"); return 0; J _______________________________________________________________________________________ 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 getuỉd(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 *stat!oc, int options); int execl(const char *path, const char * a r g 0 , ( c h a r *)0); int execlp(const char *file, const char * a r g 0 , ( c h a r *)0); int execle(const char *path, const char * a r g 0 , ( c h a r *)0, const char *envp[]); int execv(const char *path, const char *argvf]); int execvp(const char *tile, const char *argv[]); int execve(const char *path, const char *argv[], const char *envp[]); retu rn 0; } 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 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: perrorC'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 0 , getppid 0 , getuid 0 , geteuid 0 , getgid 0 , getegid 0); > 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; I_____________________________________________ 14/44 Default : break; } 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 } Int main() { Pid_t pl, p2a, p2b, p3a, p3b, p3c, p3d; PI = fork() ; // sinh 1 tu 0 Switch(pl) { 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 trinh mô phỏng hàm SYSTEM bẵng cách sử dụng các hàm FORK và EXEC. } #include finclude #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 re tu rn 0; } 14. Viết chương ừì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 #incluđe int main(int argc, char *argv[]) { char *filename; if (argc 1=2) { fprintf(stderr, "usage: useupper file\n"); exit (1); } filename = argv[l]; 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); #defme SIG_ERR (void (*)())-1 ; #define SIG DFL (void (*)()) 0; #define SIGJGN (void (*)()) 1 int kill(pid_t pid, int sig); unsigned int alarm(unsigned int seconds); int pause(void); in t sigaction(int sig, const struct sigaction *act, struct sigaction *oact); struct sigaction { void (*sa_handler)(int); /* addr of signal handler, */ sigset t sa mask; I* additional signals to block */ int sa flags; /* signal options*/ void (*sa_sigaction)(int, siginfo t *, void *); }; 16/44 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 ttinclude void catch(int signum) { static int count = 1; printf("\n An Ctrl-C lan thu:%d",count++); signal(SIGINT,catch); } int maintint arge,char *argv’]) { signal(SIGINT,catch); while (1) ; //khoiig lam j return 0; } #include finclude finclude 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 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 static void sig_alrm(int signo) { /* nothing to do, just returning wakes up sigsuspendO */ } 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.sahandler = sigalrm ; sigemptyset(&newact.sa_mask); newact.sa flags = 0; sigaction(SIGALRM, &newact, &oldact); /* block SIGALRM and save current signal mask *1 sigemptyset(&newmask); sigaddset(&newmask, SIGALRM); sigprocraask(SIG_BLOCK, &newmask, &()Idmask); alarm(nsecs); <- sử dụng hàm ALARM và SIGALRM để xây dụng SLEEP suspmask = oỉdmask; 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(O); 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: #incỉude FILE *popen(const char ^command, const char *open_mode); int pclose(FILE *stream_to_close); 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 maỉn() { FILE *read_fp; char buffer[BUFSIZ + 1]; int chars read; meraset(buffer, '\0', sizeof(buffer)); read fp = popen("ps -ax", "r"); if (read fp != NULL) { chars read = fread(bulfer, sizeot'(char), BUFS1Z, read fp); while (charsread > 0) { buffer[chars_read - 1] = '\0'; printf("Reading:-\n %s\n", buffer); chars read = fread(buffer, sizeof(char), BUFSIZ, read fp); } “ pclose(readfp); 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 I 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_pipet0], &c, 1)) >0) { putchar (c); > exit (0); } void do_parent(int data_pipe']) { int c; ____ int rc;_________________________________________________________________ 20/44 close(data_pipe[0]); while ( (c = getcharO) > 0) { rc = write(data_pipe]1], &c, 1) ; if (rc == -1) { perror("Parent: pipe write error"); close(data_pipe[1]) ; exit(1); } } close(data_pipe[1]); exit (0); } int main() { int data_pipe[2]; int pid; int rc; rc = pipe(data_pipe); if (rc == -1) { perror("pipe create error "); exit (1); } pid = fork(); switch (pid) { case -1: perror("fork error"); exit (1); case 0: do_child(data_pipe) ; default: do_parent(data_pipe) ; } return 0; } #include #include #include int main(int argc,char *argv]]) { int pipes[2]; int pid; char buf[100]; if (pipe(pipes) == -1) { perror("error:"); return 1; } //chuyen huong nhap xuat dup2(pipes[0],STDIN_FILENO); close (pipes[0]); dup2(pipes[1],STDOUT_FILENO) ; close(pipes[0]); 21/44 piđ= fork(); switch(pid) { case -1: perror("fork error:"); return 1; case 0: II child ch? d?c ->dóng d?u ghi close (1); IIghi ra stderr d? hi?n ra màn hình gets(buf); fprintf(stderr,"%s",buf) ; break; default: // parent ch? ghi -> dóng d?u d?c: close (0) ; printf("from parent: test"); } return 0; } 18. Viet 2 chương trình có nhiệm vụ như sau: a. Tiến trình A là tiến trình tạo dữ liệu, ví dụ nó tạo ra các xâu ký tự. b. Tiến trình B là tiến trinh xử lý dữ liệu, ví dụ như in ra màn hình xâu ký tự c. Tiến trình A gửi dừ liệu cho tiến trình B. Hãy minh họa công việc trên bằng cách sử dụng FIFO (named pipe). #include #include #include #include (include #include #include #include #define FIFO_NAME "/tmp/my_fifo" #define BUFFER_SIZE PIPE_BUF #define TEN_MEG (1024 * 1024 * 10) int main() { int pipe_fd; int res; int open_mode = 0_WR0NLY; int bytes_sent = 0; char buffer[BUFFER_SIZE - 1]; if (access(FIFO_NAME, F_OK) == -1) { res = mkfifo(FIFO_NAME, 0777); if (res != 0) { fprintf (stderr, "Could not create fifo %s\n", FIF 0_NAM E); exit(EXIT_FAILURE) ; } } printf("Process %d opening FIFO 0_WR0NLY\n", g etpid()) ;____________________________________________________________________ 22/44 pipe_fd = open(FIFO_NAME, open_mode); printf("Process %d result %d\n", getpid(), pipe_fd); if (pipe_fd != -1) { while(bytes_sent < ?EN_MEG) { res = write (pipe_fd, buffer, BUFFERjSIZE); if (res == -1) { fprintf(stderr, "Write error on pipe\n"); exit(EXIT_FAILURE); } bytes_sent += res; } (void)close(pipe_fd) ; } else { exit(EXIT_FAILURE); } printf ( "Process %d finished\n", getpidO); exit(EXIT_SUCCESS); //include nhu tren #include ttdefine FIFO_NAME "/tmp/my_fifo" #define BUFFER_SIZE PIPE_BUF int mainO { int pipe_fd; int res; int open_mode = 0_RD0NLY; char buffer[BUFFER_SIZE - 1]; int bytes_read = 0; memset(buffer, '\0', sizeof(buffer)); printf("Process %d opening FIFO 0_RD0NLY\n", getpi d ( ) ) ; pipe_fd = open(FIFO_NAME, open_mode); printf ("Process %d result %d\n”, getpidO, pipe_fd) ; if (pipe_fd != -1) { do { res = read(pipe_fd, buffer, BUFFER_SIZE); bytes_read += res; } while (res >0) ; (void)close(pipe_fd) ; } else { exit(EXIT_FAILURE); } printf("Process %d finished, %d bytes read\n", getpidO, bytes_read) ; exit(EXIT_SUCCESS); } ProgA.c 23/44 #include #include #include #define FIFO_NAME "/tmp/testfifo" int main(int argc,char *argv]]) { int fd; if (access(FIF0_NAME,F_0K)==-1) if (mkfifo(FIFO_NAME,0777) != 0 ) { perror("make fifo:"); return 1; } fd = open(FIFO_NAME,0_WR0NLY) ; if (fd != -1) { write(fd, "hello",PIPE_BUF); close(fd); } return 0; }ProgB.c ♦include ♦include ♦include ♦define FIFO_NAME "/tmp/testfifo" int main(int argc,char *argv[]) { int fd; char buf[PIPE_BUF+1] fd = open(FIF0_NAME,0_WR0NLY) ; if (fd != -1) { read(fd,buf,PIPE_BUF); printf("receive: %s",buf); close(fd); } else { fprintf(stderr,"pipe not exist"); return 1; } return 0; Message Queues 24/44 int msgctl(int msqid, int cmd, struct msqidds *buf); int msgget(key_t key, int msgflg); int msgrcv(int msqid, void *msg_ptr, s i ze t msgsz , long int msgtype, int msgflg); int msgsnd(int msqid, const void *msg_ptr, size t msg sz, int msgflg); struct msqid ds { struct ipc_perm msg perm; struct msg *msg_first; /* first message on queue, unused */ struct msg *msg_last; /* last message in queue, unused */ _kernel_time_t msg stime; /* last msgsnd time */ _kernel_time_t msg rtime; /* last msgrcv time *1 _kernel_time_t msg ctime; /* last change time */ unsigned long msg lcbytes: /* Reuse junk fields for 32 bit */ unsigned long msglqbytes; /* ditto */ unsigned short msg cbytes; /* current # of bytes on queue */ unsigned short msg qnum; /* number of messages in queue */ unsigned short msg qbytes; /* max number of bytes on queue */ __kernel_ipc_pid_t msg lspid; /* pid of last msgsnd */ _kernel_ipc_pid_t msg lrpid; /* last receive pid */ }; struct ipc_perm { __k e y t __key; _uid t uid; __gid_t gid; __uid t cuid; gid t cgid; unsigned short int mode; }; struct msgbuf { long mtype; /* type of message */ char mtextfl]; /* message text */ 1; /* Key */ /* Owner's user ID. */ /* Owner's group ID. */ /* Creator's user ID. */ /* Creator's group ID. */ /* Access permission. */ Trong 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 iinclude #include #incluđe 25/44 ♦include "queue defs.h" struct msgbuf { long int mtype; char mtext[1]; } ; int main(int argc, char* argv[]) { int queue id; struct msgbuf* msg; int i; int rc; queue_id = msgget(QUEUE_ID, IPC_CREAT | 0777); if (queue_id == -1) { perror("main: msgget error"); exit (1); } printf("message queue created, queue id '%d'.\n", queue_id); msg = (struct msgbuf*)malloc(sizeof( struct msgbuf)+MAX_MSG_SIZE); for (i=l; i <= NUM_MESSAGES; i++) { msg->mtype = (i % 3) + 1; sprintf(msg->mtext, "hello world - %d", i) ; rc = msgsnd(queue_id, msg, strlen(msg->mtext)+1, 0); if (rc == -1) { perror("main: msgsnd error"); exit (1); } } free(msg); printf("generated %d messages, exiting.\n", M_MESSAGES); NU return 0; } ♦include ♦include ♦include ♦include ♦include ♦include ♦include "queue_defs.h" struct msgbuf{ long int mtype; char mtext[1]; } ; 26/44 int main(int argc, char *argv[]) { int queue_id; struct msgbuf* msg; int rc; int msg_type; if (argc != 2) { fprintf(stderr, "Usage: %s \n". argv[ 0 ]); fprintf(stderr, must be 3. \n") ; } exit (1); msg_type = atoi(argv[1]); if (msg_type 3) { fprintf(stderr, "Usage: %s \n", between 1 and argv[0]); fprintf(stderr, and 3.\n"); exit (1) ; } must be between 1 queue_id = msgget(QUEUE_ID, 0); if (queue_id == -1) { perror("main: msgget error") ; exit(1); } printf("message queue opened, queue id '%d'.\n", queue_id); msg = (struct msgbuf*)malloc(sizeof( struct msgbuf)+MAX_MSG_SIZE) ; while (1) { rc = msgrcv(queue_id, msg, MAX_MSG_SIZE+1, g_type, 0); if (rc == -1) { perror("main: msgrcv error"); exit (1); } printf("Reader '%d' read message: '%s'\n", >mtext); ms msg_type, msg- sleep (1); } return 0; ProgA.c ♦include ♦include ♦include 27/44 #include #include #include #define MSGQID 1234 #define MAX_LEN 256 struct msgbuf { long mtype; char mtext[1]; } *msg; int main(int argc,char *argv^]) { int qid; int ret; qid = msgget(MSGQID, IPC_CREAT | 0777); if (qid == -1) { perror("msgget error:"); return 1; } msg = (struct msgbuf *) malloc(sizeof(struct msgbuf) + MAX_LEN); msg->mtype=0; strcpy(msg->mtext,"From Process A"); ret = msgsnd(qid, msg, strlen(msg->mtext)+1,0); if (ret == -1) { perror("msgsnd error:"); return 1; } return 0; ProgB.c #include #include ♦include ♦include ♦include ♦include ♦define MSGQID 1234 ♦define MAX_LEN 256 struct msgbuf { long mtype; char mtext[1]; } *msg; int main(int argc,char *argv^]) { int qid; int ret; qid = msgget(MSGQID, 0); if (qid == -1) { 28/44 perror{"msgget error:"); return 1; msg = (struct msgbuf *) malloc(sizeof(struct msgbuf) + MAX_LEN); ret = msgrcv(qid, msg, MAX_LEN + 1,0,0); if (ret == -1) { perror("msgsnd error:"); return 1; } printf("Process B received: %s",msgbuf->mtext); return 0; } } Tested by HCricket /'/ProA.c ♦include ♦include ♦include ♦include ♦include ♦define MSGSZ 128 /* * Declare the message structure. */ -ypedef struct msgbuf { long mtype; char mtext[MSGSZ]; } message_buf; main () { int msqid; int msgflg = IPC_CREAT | 0666; key_t key; message_buf sbuf; size_t buf_length; /* * Get the message queue id for the * "name" 1234, which was created by * the server. */ key = 1234; (void) fprintf(stderr, "\nmsgget: Calling msgget(%^lx,\ %#o)\n", key, msgflg); if ((msqid = msgget(key, msgflg )) < 0) { perror("msgget"); exit (1); } else (void) fprintf(stderr,"msgget: msgget succeeded: msqid = %d\n", msqid); 29/44 /* * We'll send message type 1 */ sbuf.mtype = 1; (void) fprintf(stderr,"msgget: msgget succeeded: msqid = %d\n", msqid); (void) strcpy(sbuf.mtext, "Did you get this?"); (void) fprintf(stderr,"msgget: msgget succeeded: msqid = %d\n", msqid); buf_length = strlen(sbuf.mtext) + 1 ; /* * Send a message. */ if (msgsnd(msqid, Ssbuf, buf_length, IPC_NOWAIT) < 0) { printf ("%d, %d, %s, %d\n", msqid, sbuf.mtype, sbuf.mtext, buf_length); perror("msgsnd"); exit (1); } else printf("Message: \"%s\" Sent\n", sbuf.mtext); exit (0); } //ProB.c ♦include ♦include ♦include ♦include ♦define MSGSZ 128 ,/* * Declare the message structure. */ typedef struct msgbuf { long mtype; char mtext[MSGSZ]; } message_buf; main () { int msqid; key_t key; message_buf rbuf; /* * Get the message queue id for the * "name" 1234, which was created by * the server. */ key = 1234; 30/44 if ((msqid = msgget(key, 0666)) < 0) { perror("msgget"); exit (1); } /* * Receive an answer of message type 1. */ if (msgrcv(msqid, Srbuf, MSGSZ, 1, 0) < 0) { perror("msgrcv"); exit(1); } /* * Print the answer. */ printf("%s\n", rbuf.mtext); exit (0); Shared Memory void *shmat(int shmid, const void *shm_addr, int shmflg); int shmctl(int shm id, int cmd, struct shmidds *buf); int shmdt(const void *shm_addr); int shmget(key_t key, s i ze t size, int shmflg); struct shmid ds { struct ipc_perm shm_perm; /* operation permission struct size t shm segsz; /* size of segment in bytes */ _t imet shm atime; _time t shm dtime; _time t shm ctime; _pid t shm cpid; _pid t shm lpid; shmatt_t shm nattch; */ /* time of last shmato */ /* time of last shmdto */ /* time of last change by shmctio */ /* pid of creator */ /* pid of last shmop */ /* number of current attaches */ Trong phần này có 1 số bài tập như sau: 21. Xây dựng chưong trình quản lý Shared Memory như: a. Tạo, hủy đối tượng Shared Memory. b. Ghi, đọc dừ liệu từ bộ nhớ dùng chung. c. Đọc các thông tin của Shared Memory như: quyền truy cập, người sử dụng,... 22. Viết 2 chương trình trao đổi dữ liệu với nhau thông qua Shared Memory . ♦include ♦include ♦include ♦include 31/44 struct country { char name[30]; char capital_city[30]; char currency[30]; int population; int main() { int shm_id; char* shm_addr; int* countries_num; int* stop; struct country* countries; struct shmid_ds shm_desc; int i; shm_id = shmget(100, 2048, 0777); if (shm_id == -1) { perror ("main: shmget error "); exit (1); } shm_addr = shmat(shm_id, NULL, 0); if (!shm_addr) { perror("main: shmat error "); exit (1); } countries_num = (int*) shm_addr; stop = (int*) ((void*)shn_addr+sizeof(int)); countries = (struct country*) ((void*)shm_addr+sizeof(int)*2); printf ("Total %d \n", (*countries_num)); for (i=0; i < (*countries_num) ; i++) { printf("Countery %d:\n", i+1); printf(" name: %s:\n", countries[i].name); printf(" capital city: %s:\n", countries[i].capital_city); printf(" currency: %s:\n", countries[i].currency); printf (" population: %d:\n", countries[i].population); } printf("Now try to stop writer \n"); *Stop=l; return 0; ♦include ♦include ♦include ♦include struct country { char name[30]; ____char capital city[30]; 32/44 char currency[30]; int population; } ; int main() { int shm_id; char* shm_addr; int* countries_num; :nt* stop; struct country* countries; struct shmid_ds shm_desc; int i; shm_id = shmget(10 0, 2048, IPC_CREAT | 0777); if (shm_id == -1) { perror("main: shmget error "); exit (1); } shm_addr = shmat(shm_id, NULL, 0); if (!shm_addr) { perror("main: shmat error "); exit (1); } countries_num = (int*) shm_addr; *countries_num = 0; stop =(int*) ((void*)shm_addr+sizeof(int)); *stop=0; countries = (struct country*) ((void*)shm_addr+sizeof(int)*2); strcpy(countries[0].name, "U.S.A"); strcpy(countries[0].capital_city, "Washington"); strcpy(countries[0].currency, "U.S. Dollar"); countries[0].population = 250000000; (*countries_num)++; strcpy(countries[1]. name, "Israel"); strcpy(countries[1].capital_city, "Jerusalem"); strcpy(countries[1].currency, "New Israeli Shekel"); countries[1].population = 6000000; (*countries_num)++; strcpy (countries[2]. name, "France"); strcpy(countries[2].capital_city, "Paris"); strcpy(countries[2].currency, "Frank"); countries[2].population = 30000000; (*countries_num)++; printf("Waiting for other process reading data \n"); fflush(stdout); while (! (*stop)) { sleep (1); } if (shmdt(shm_addr) == -1) { perror("main: shmdt: "); } 33/44 if (shmctl(shm_id, IPC_RMID, &shm_desc) == -1) { perror("main: shmctl error "); } printf("main writer finished \n") ; return 0; } ProgA.c ♦include ♦include ♦include ♦include ♦define SHMID 1234 ♦define MAX LEN 256 int main(int argc,char *argv]]) { int id; int ret; char * shm addr; int * size; char * msg; // tao vung nho chung id = shmget(SHMID , MAX LEN, IPC CREAT if (id == -1) { perror("shmget error:"); return 1; } 0777); // attach shm addr = shmat(id , NULL , 0); if ( !shm addr ) { perror("shmat error:"); return 1; } // ghi du lieu vao vung nh strcpy(msg,"From Process A size = (int *)shm addr; *size = sizeof(msg); strcpy(shm addr + sizeof(i //detach ret = shmdt(shm addr); if (ret == -1) { perror("shmdt error: return 1; } return 0; } P r o g B .c 34/44 ♦include ♦include ♦include ♦include ♦define SHMID 1234 ♦define MAX LEN 256 int main(int argc,char *argv]]) { int id; int ret; char * shm_addr; int * size; char * msg; // tao vung nho chung id = shmget(SHMID , MAX_LEN, 0777); if (id == -1) { perror("shmget error:"); return 1; } II attach shm_addr = shmat(id , NULL , 0) ; if ( !shm_addr ) { perror("shmat error:"); return 1; } // doc du lieu tu vung nho chung size = (int *)shm_addr; strncpy(msg, shm_addr + sizeof(int) , printf("Process B received: %s", msg); //detach ret = shmdt(shm_addr); if (ret == -1) { perror("shmdt error:"); return 1; } return 0; }____________________________________________ *size); 35/44 Tested by HouseCricket ProgA.c ♦include ♦include ♦include ♦include ♦define SHMSZ 27 main () { char c; int shmid; key_t key; char *shm, *s; /* * We'll name our shared memory segment * "5678". */ key = 567 8; /* * Create the segment. */ if ((shmid = shmget(key, SHMSZ, IPC_CREAT | 0666)) < 0) { perror("shmget"); exit (1); } /* * Now we attach the segment to our data space. */ if ((shm = shmat(shmid, NULL, 0)) == (char *) -1) { perror("shmat"); exit (1); } /* * Now put some things in~o the memory for the * other process to read. */ s = shm; for (c = 'a'; c <= ’z'; C++) *s++ = c; *s = NULL; /* * Finally, we wait until the other process * changes the first character of our memory * to '*', indicating tha" it has read what * we put there. */ while (*shm != '*') sleep(1); exit (0); } //ProgB.c 37/44 Semaphores #include int semctl(int semid, int sem num, int command,...); int semget(key_t key, int numsems, int sem flags); int semop(int sem id, struct sembuf *sem_ops, size_t num sem ops); Trong phần này có 1 số bài tập như sau: 23. Xây dựng chưong trình quản lý Semaphores như: a. Tạo, hủy đối tượng Semaphores. b. Xây dựng các thao tác làm việc với Semaphores. c. Đọc các thông tin của Semaphores như: quyền truy cập, người sử dụng, ... 24. Viết 2 chương trình trao đổi dữ liệu với nhau thông qua Shared Memory và Semaphores. ♦include ♦include ♦include ♦include ♦include ệinclude ♦include ♦include ♦include ♦define SEM_ID 250 union semun { int val; struct semid_ds *buf; unsigned short int *array; }; struct country { char name[30]; char capital_city[30]; char currency[30]; int population; } ; void random_delay() { static int initialized = 0; int random_num; struct timespec delay; if (¡initialized) { srand(time(NULL) ) ; initialized = 1; } random_num = rand() % 10; delay.tv_sec = 0; delay.tv_nsec = 10*randon_num; nanosleep(Sdelay, NULL); } void sem lock(int sem set id)____ 38/44 struct sembuf sem_op; sem_op.sem_num = 0; s em_op.sem_op = -1; sem_op.sem_flg = 0; semop(sem_set_id, &sem_op, 1) ; } void sem_unlock(int sem_set_id) { struct sembuf sem_op; sem_op.sem_num = 0; sem_op.sem_op = 1; sem_op.sem_flg = 0; semop(sem_set_id, &sem_op, 1); } void add_country(int sem_set_id, int* countries_num, struct country* countries, char* country_name, char* capital_city, char* currency, int population) { sem_lock(sem_set_id); strcpy(countries[*countr:es_num].name, country_name); strcpy (countries [ *countnes_num] . capital_city, capital_city); strcpy (countries [*countnes_num] . currency, currency); countries [*countries_nurrf .population = population; (*countries_num)++; sem_unlock(sem_set_id) ; } { void do_child(int sem_set_id, int* countries_num, struct country* counties) { add_country(sem_set_id, countries_num, counties, "U.S.A", "Washington", "U.S. Dollar", 250000000); random_delay(); add_country(sem_set_id, countries_num, counties, "Israel", "Jerusalem", "New Israeli Shekel", 6000000); random_delay(); add_country(sem_set_id, countries_num, counties, "France", "Paris", "Frank", 60000000); 39/44 random_delay(); add_country(sem_set_id, countries_num, counties, "Great Britain", "London", "Pound", 55000000); } void do_parent(int sem_set_id, int* countries_num, struct country* countries) { int i, num_loops; for (num_loops=0; num_loops < 5; num_loops++) { sem_lock(sem_set_id); printf ("------------------------------- \n") ; printf("Number Of Countries: %d\n", *countries_num); for (i=0; i < (*countries_num); i++) { printf("Country %d:\n", i+1); printf(" name: %s:\n", countries[i].name); printf (" capital city: %s:\n", countries[i].capital_city); printf(" currency: %s:\n", countries[i].currency); printf (" population: %d:\n", countries[i].population); } sem_unlock(sem_set_id) ; random_delay(); } } int main() { int sem_set_id; union semun sem_val; int shm_id; char* shm_addr; int* countries_num; struct country* countries; struct shmid_ds shm_desc; int rc; pid_t pid; sem_set_id = semget(SEM_ID, 1, IPC_CREAT | 0777); if (sem_set_id == -1) { perror("main: semget"); exit (1); } sem_val.val = 1; rc = semctl(sem_set_id, 0, SETVAL, sem_val); if (rc == -1) { perror("main: semctl"); exit (1); 40/44 } shm id = shmget(100, 2048, IPC_CREAT | IPC_EXCL if (shm id == -1) { perror("main: shmget error"); exit (1); } 0600); shm addr = shmat(shm id, NULL, 0); if (!shm addr) { perror("main: shmat error "); exit (1); } countries num = (int*) shm addr; *countries num = 0; countries = (struct country*) ((void*)shm addr+sizeof(int)); pid = fork(); switch (pid) { case -1: perror("fork error "); exit (In­ break; case 0: do child(sem set id, countries num, countries); exit (0); break; default: do parent (sem set id, countries num, countries); break; } { int child status; wait(&child status); } if (shmdt(shm addr) == -1) { perror("main: shmdt error "); } if (shmctl(shm id, IPC RMID, &shm desc) == -1) { perror("main: shmctl error "); } return 0; } ProgA.c ♦include ♦include ♦include ♦include ♦include ♦define SEMID 4321 41/44 ♦define SHMID 1234 ♦define MAX LEN 256 int main(int argc,char *argv]]) { int id, semid; char * shm_addr; int * size; char * msg; union semun semval; struct sembuf sb; // tao vung nho chung id = shmget(SHMID , MAX_LEN, IPC_CREAT | 0777); II attach shm_addr = shmat(id , NULL , 0); II tao semaphore semid = semget(SEMID , 1, 0777); II khoi tao semaphore = 1 semval.val = 1; semctl(semid, 0 , SETVAL, semval); II giam semaphore di 1, cho ghi du lieu sb.sem_num = 0; sb.sem_op = -1; sb. sem_flg = 0; semop(semid, &sb, 1); II ghi du lieu vao vung nho chung strcpy(msg,"From Process A"); size = (int *)shm_addr; *size = sizeof(msg); strcpy (shm_addr + sizeof (int), msg); II tang semaphore len 1 , cho phep doc du lieu sb.sem_op = 1; semop(semid, &sb, 1); //detach shmdt(shm_addr); return 0; } ProgB.c ♦include ♦include ♦include ♦include ♦include ♦define SEMID 4321 ♦define SHMID 1234 ♦define MAX LEN 256 int main(int argc,char *argv]]) { int id, semid; char * shm_addr; int * size; char * msg; union semun semval; struct sembuf sb;____________ 42/44 // tao vung nho chung id = shmget(SHMID , MAX_LEN, 0777); II attach shm_addr = shmat(id , NULL , 0); II tao semaphore semid = semget(SEMID , 1, 0777); II giam semaphore di 1, cho doc du lieu sb.sem_num = 0; sb.sem_op = -1; sb. sem_flg = 0; semop(semid, &sb, 1); II doc du lieu tu vung nho chung size = (int *)shm_addr; strncpy(msg, shm_addr + sizeof(int) , *size); II tang semaphore len 1 , cho phep ghi du lieu sb.sem_op = 1; semop(semid, &sb, 1); printf("Process B received: %s", msg); //detach shmdt(shm_addr); return 0; 43/44 Tested by Housecricket .//ProA. c ♦include ♦include ♦include ♦include ♦include ♦define SEMKEYPATH "/dev/null" /* Path used on ftok for semget key */ ♦define SEMKEYID 1 /* Id used on ftok for semget key */ ♦define SHMKEYPATH "/dev/null" /* Path used on ftok for shmget key */ ♦define SHMKEYID 1 /* Id used on ftok for shmget key */ ♦define NUMSEMS 2 /* Num of sems in created sem set */ ♦define SIZEOFSHMSEG 50 /* Size of the shared mem segment */ ♦define NUMMSG 2 /* Server only doing two "receives" on shm segment */ int main(int argc, char *argv[]) { int rc, semid, shmid, i; key_t semkey, shmkey; void *shm_address; struct sembuf operations[2]; struct shmid_ds shmid_struct; short sarray[NUMSEMS]; /* Generate an IPC key for the semaphore set and the shared */ /* memory segment. Typically, an application specific path and */ /* id would be used to generate the IPC key. */ semkey = ftok(SEMKEYPATH,SEMKEYID); if ( semkey == (key_t)-l ) { printf("main: ftok() for sem failed\n"); return -1; } shmkey = ftok(SHMKEYPATH,SHMKEYID); if ( shmkey == (key_t)-l ) { printf("main: ftok() for shm failed\n"); return -1; } /* Create a semaphore set using the IPC key. The number of */ /* semaphores in the set is two. If a semaphore set already */ /* exists for the key, rezurn an error. The specified permissions*/ /* give everyone read/write access to the semaphore se~. */ semid = semget( semkey, NUMSEMS, 0666 | IPC_CREAT | IPC_EXCL ); if ( semid == -1 ) { printf("main: semget ( | failed\n"); return -1; } /* Initialize the first semaphore in the set to 0 and zhe */ /* second semaphore in the set to 0. */ I * ★ I /* The first semaphore in the sem set means: */ /* '1' — The shared memory segment is being used. */ /* '0' — The shared memory segment is freed. */ /* The second semaphore in the sem set means: */ /* '1' — The shared memory segment has been changed by */ /* the client. */ /* '0' — The shared memory segment has not been */ /* changed by the client. */ sarray[0] = 0; 44/44 sarray[1] = 0;

Các file đính kèm theo tài liệu này:

  • pdfontapc_duong_3358.pdf
Tài liệu liên quan