Tải bản đầy đủ (.pdf) (44 trang)

Giáo án - Bài giảng: CÁC NỘI DUNG CẦN ÔN TẬP VỚI C TRONG KHI HỌC C

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (718.23 KB, 44 trang )

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 <unistd.h>
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 <stdio.h>
iinclude <unistd.h>
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 <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>
iinclude <stdio.h>
#include <string.h>
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 <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);
Cac ham truy cap den thuoc tinh cua file
3/44
#include <sys/stat.h>
int stat(const char *restrict pathname, struct stat *restrict buf);
int fstat(int filedes, struct stat *buf);
struct stat {
m odet stmode; /* 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 <stdio.h>
FILE *fopen(const char *filename, const char *mode);
sizet fread(void *ptr, size_t size, size_t nitems, FILE *stream);
sizet 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 <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[l] || !argv[2]) {
fprintf(stderr, "Usage: %s <source tile path>
<target file path>\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 <sỵs/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==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 <sỵs/stat.h>
#include <fcntl.h>

#include <unistd.h>
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 <sỵs/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sỵs/types.h>
#include <stdio.h>
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 <unistd.h>
#include <stdio.h>
#include <dirent.h>
#include <strinq.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 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 <dir_name> <max_depth>",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 <stdio.h>
finclude <unistd.h>
finclude <string.h>
#include <malloc.h>
void main(int arge, char* argv[])
{
char* file_path;
char* dir_path;
char* p_slash;
if (arge != 2 || !argv[i;) {
fprintf(stderr,
"Usage: %s <full file path>\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 <sys\stat.h>
#include <fcntl.h>
tinclude <unistd.h>
#include <io.h>
int main(int argc,char *argv[])
{
if (argc < 2)
{
printf(”\n Usage: %s <file_name>",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 <sỵs\stat.h>
#include <fcntl.h>
#include <unistd.h>

#include <io.h>
#include <stdlib.h>
#include <string.h>
int main(int argc,char *argv'])
{
char path[256], *ptr, *buf;
int len = 0;
if (argc < 2)
{
printf("\n Usage: %s <file_name>",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 *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 *argvf]);
int execvp(const char *tile, const char *argv[]);
int execve(const char *path, const char *argv[], const char *envp[]);
return 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 <unistd.h>
#include <stdio.h>
#include <sys/types.h>
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 <sys/types.h>
finclude <unistd.h>
#include <stdio.h>

#include <sys/wait.h>
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
return 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 <unistd.h>
#incluđe <stdio.h>
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 <signal.h>
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);
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; 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 <stdio.h>
ttinclude <signal.h>
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 <stdio.h>
finclude <unistd.h>
finclude <signal.h>
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 <stdio.h>

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 <stdio.h>
ệinclude <unistd.h>
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 <unistd.h>
#include <stdio.h>
#include <signal.h>
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 <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
(include <fcntl.h>
#include <limits.h>
#include <sỵs/tỵpes.h>
#include <sys/stat.h>
#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_NAME);
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 <sys/stat.h>
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 <unistd.h>

#include <stdio.h>
#include <signal.h>
#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 <unistd.h>
♦include <stdio.h>
♦include <signal.h>
♦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, sizet 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
{
__
keyt
__
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
<stdio.h>
<stdlib.h>
<sỵs/tỵpes-h>
<sỵs/ipc.h>
<sys/msg.h>
25/44

×