├── README.md ├── chapter1 ├── 01.c └── my_more.c ├── chapter10 ├── close-then-open.c ├── fork-exec.c ├── open-close-dup-close.c └── pipe.c ├── chapter11 ├── ntp_client.c ├── ntp_server.c └── popen.c ├── chapter15 ├── lock_client.c ├── lock_server.c ├── select.c ├── shmget_client.c └── shmget_server.c ├── chapter2 ├── my_cp.c └── my_who.c ├── chapter3 └── my_ls.c ├── chapter4 └── my_pwd.c ├── chapter5 ├── echo_stat.c ├── my_stty.c ├── my_write.c └── set_stat.c ├── chapter6 └── my_play.c ├── chapter7 └── my_timer.c ├── chapter8 └── my_shell.c └── chapter9 └── my_shell.c /README.md: -------------------------------------------------------------------------------- 1 | 大三上学期
2 | 书籍《linux编程实践教程》
3 | 代码集合
4 | 都是我一手一脚码的
5 | 亲测有效
6 | -------------------------------------------------------------------------------- /chapter1/01.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(){ 4 | 5 | int c; 6 | while( (c = getchar()) != EOF ){ 7 | putchar(c); 8 | } 9 | 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /chapter1/my_more.c: -------------------------------------------------------------------------------- 1 | /********************** 2 | *2016.12.2 3 | *有重定向功能 4 | * 5 | * 6 | **********************/ 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #define PAGE_LEN 24 //每页24行 13 | #define LINE_LEN 512 //每行最多512字节 14 | 15 | void more(FILE *); 16 | 17 | int main(int argc, char *argv[]){ 18 | char buffer[LINE_LEN]; 19 | 20 | FILE *pf; 21 | 22 | if(argc == 1){ 23 | //fgets(buffer, LINE_LEN, stdin); 24 | more(stdin); //用重定向是从这里输入的 25 | }else{ 26 | //strcpy(buffer, argv[1]); 27 | while(--argc){ 28 | if((pf = fopen(*++argv, "r")) != NULL){ 29 | more(pf); 30 | fclose(pf); 31 | }else 32 | break; 33 | } 34 | } 35 | /* 36 | if( (pf = fopen(buffer, "r")) == NULL ){ 37 | printf("打开文件失败!\n"); 38 | return 0; 39 | } 40 | more(pf); 41 | */ 42 | return 0; 43 | } 44 | 45 | void more(FILE *pf){ 46 | 47 | FILE *ptty; //从/dev/tty获取数据 48 | char line_buffer[LINE_LEN]; //存放文件读出来的一行内容 49 | int line_read_num = 0; //已读的行数 50 | int getchar_num = 0; 51 | char c; 52 | 53 | //打开文件 54 | 55 | 56 | if((ptty = fopen("/dev/tty", "r")) == NULL){ 57 | printf("打开tty失败!\n"); 58 | exit(0); 59 | } 60 | 61 | //循环输出文件内容,每输出24行则等待输入,没到24行则退出程序 62 | while(fgets(line_buffer, LINE_LEN, pf)){ 63 | 64 | //如果输出了24行 65 | if(line_read_num == PAGE_LEN){ 66 | printf("\n\033[7m more? \033[m"); 67 | while((c = getc(ptty)) != EOF){ //这儿的数据是/dev/tty传入的 68 | if(c == 'q'){ 69 | fclose(pf); 70 | exit(0); 71 | } 72 | else if(c == '\n'){ 73 | getchar_num = 1; 74 | break; 75 | } 76 | else if(c == ' '){ 77 | getchar_num = 24; 78 | break; 79 | } 80 | } 81 | 82 | line_read_num -= getchar_num; 83 | } 84 | 85 | // 86 | if(fputs(line_buffer, stdout) == EOF){ 87 | exit(0); 88 | } 89 | 90 | line_read_num++; 91 | } 92 | 93 | fclose(ptty); 94 | fclose(pf); 95 | } 96 | -------------------------------------------------------------------------------- /chapter10/close-then-open.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define BUFFER_SIZE 1024 6 | 7 | int main(int argc, char *argv){ 8 | 9 | char buffer[BUFFER_SIZE]; 10 | 11 | fgets(buffer, BUFFER_SIZE, stdin); 12 | printf("%s", buffer); 13 | 14 | 15 | 16 | 17 | close(0); 18 | 19 | //这儿打开的是0标识符,所以用if(!pf)会出文件 20 | int pf = open("/etc/passwd", O_RDONLY); 21 | printf("%d", pf); 22 | 23 | fgets(buffer, BUFFER_SIZE, stdin); 24 | printf("%s", buffer); 25 | 26 | return 0; 27 | } -------------------------------------------------------------------------------- /chapter10/fork-exec.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include //fork 4 | #include //wait 5 | #include 6 | 7 | int main(int argc, char *argv[]){ 8 | 9 | int pid = fork(); 10 | 11 | //如果是子进程 12 | if(pid == 0){ 13 | close(1); 14 | creat("test.c", 0755); 15 | execlp("who", "who", NULL); 16 | exit(1); 17 | 18 | }else{ 19 | wait(NULL); 20 | printf("done\n"); 21 | } 22 | 23 | 24 | 25 | 26 | return 0; 27 | } -------------------------------------------------------------------------------- /chapter10/open-close-dup-close.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define BUFFER_SIZE 1024 6 | 7 | int main(int argc, char *argv){ 8 | 9 | char buffer[BUFFER_SIZE]; 10 | 11 | fgets(buffer, BUFFER_SIZE, stdin); 12 | printf("%s", buffer); 13 | 14 | 15 | 16 | int pf = open("/etc/passwd", O_RDONLY); 17 | printf("pf: %d\n", pf); 18 | 19 | close(0); 20 | 21 | int newpf = dup(pf); 22 | printf("newpf: %d\n", newpf); 23 | 24 | close(pf); 25 | 26 | 27 | 28 | fgets(buffer, BUFFER_SIZE, stdin); 29 | printf("%s", buffer); 30 | 31 | return 0; 32 | } -------------------------------------------------------------------------------- /chapter10/pipe.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | #define BUFFER_SIZE 1024 9 | #define oops(m,x) {printf(m); exit(x);} 10 | 11 | 12 | int main(int argc, char *argv[]){ 13 | 14 | int argList[2]; 15 | char send_buffer[BUFFER_SIZE] = ""; 16 | char recv_buffer[BUFFER_SIZE] = ""; 17 | int len; 18 | 19 | int read_pipe = creat("read", 0755); 20 | int write_pipe = creat("write", 0755); 21 | 22 | argList[0] = read_pipe; 23 | argList[1] = write_pipe; 24 | 25 | 26 | printf("%d %d", argList[0], argList[1]); 27 | if( pipe(argList) == -1) 28 | oops("pipe", -1); 29 | 30 | switch(fork()){ 31 | case -1: 32 | oops("fork: ", -1); 33 | break; 34 | 35 | //子进程write 36 | case 0: 37 | close(argList[0]); 38 | if( dup2(argList[1], 1) == -1) 39 | oops("dups2: ", -1); 40 | 41 | execlp("cat", "who", "/etc/passwd", NULL); 42 | exit(0); 43 | //父进程read,读完后输出结果 44 | default: 45 | sleep(1); 46 | close(argList[1]); 47 | if( dup2(argList[0], 0) == -1) 48 | oops("dup2: ", -1); 49 | 50 | execlp("head", "head", "-1", NULL); 51 | } 52 | 53 | return 0; 54 | } -------------------------------------------------------------------------------- /chapter11/ntp_client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include //memset 9 | 10 | 11 | #define oops(m, x) {perror(m); exit(x);} 12 | #define BUFFER_SIZE 1024 13 | 14 | int main(int argc, char *argv[]){ 15 | 16 | struct sockaddr_in server_addr; 17 | int client_socket; 18 | FILE *client_pf; 19 | 20 | char recv_buffer[BUFFER_SIZE]; 21 | 22 | //建立socket 23 | client_socket = socket(PF_INET, SOCK_STREAM, 0); 24 | 25 | //填充IP信息 26 | server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 27 | server_addr.sin_port = 6666; 28 | server_addr.sin_family = AF_INET; 29 | 30 | 31 | //连接 32 | if( connect(client_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1 ) 33 | oops("connect: ", -1); 34 | 35 | 36 | memset(recv_buffer, 0, BUFFER_SIZE); 37 | //读数据 38 | client_pf = fdopen(client_socket, "r"); 39 | fgets(recv_buffer, BUFFER_SIZE, client_pf); 40 | 41 | printf("%s\n", recv_buffer); 42 | 43 | close(client_socket); 44 | 45 | return 0; 46 | } -------------------------------------------------------------------------------- /chapter11/ntp_server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define oops(m, x) {perror(m); exit(x);} 10 | 11 | 12 | int main(int argc, char *argv[]){ 13 | 14 | struct sockaddr_in server_addr, client_addr; 15 | int server_socket, client_socket; 16 | FILE *client_pf; 17 | 18 | time_t current_time; 19 | 20 | //建立socket 21 | server_socket = socket(PF_INET, SOCK_STREAM, 0); 22 | 23 | //填充IP信息 24 | server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 25 | server_addr.sin_port = 6666; 26 | server_addr.sin_family = AF_INET; 27 | 28 | //绑定 29 | if( bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)) != 0) 30 | oops("bind: ", -1); 31 | 32 | //监听 33 | if( listen(server_socket, 1) != 0 ) 34 | oops("listen: ", -1); 35 | 36 | while(1){ 37 | 38 | int len = sizeof(client_addr); 39 | if( (client_socket = accept(server_socket, (struct sockaddr*)&client_addr, &len)) == -1) 40 | oops("accept: ", -1); 41 | 42 | client_pf = fdopen(client_socket, "w"); 43 | if(client_pf == NULL) 44 | oops("fdopen: ", -1); 45 | 46 | 47 | current_time = time(NULL); 48 | fprintf(client_pf, "The time is : %s", ctime(¤t_time)); 49 | fclose(client_pf); 50 | 51 | } 52 | 53 | close(server_socket); 54 | close(client_socket); 55 | 56 | return 0; 57 | } -------------------------------------------------------------------------------- /chapter11/popen.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define BUFFER_SIZE 1024 4 | 5 | int main(int argc, char *argv[]){ 6 | 7 | FILE *pf = popen("cat /etc/passwd", "r"); 8 | char buffer[BUFFER_SIZE]; 9 | 10 | while( fgets(buffer, BUFFER_SIZE, pf) ){ 11 | printf("%s", buffer); 12 | } 13 | 14 | pclose(pf); 15 | 16 | return 0; 17 | } -------------------------------------------------------------------------------- /chapter15/lock_client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void lock_opeartion(int, int); 6 | 7 | int main(int argc, char*argv[]){ 8 | 9 | int fd = 0; 10 | char current_time[1024]; 11 | 12 | fd = open("test.txt", O_CREAT|O_RDONLY); 13 | 14 | while(1){ 15 | lock_opeartion(fd, F_RDLCK); 16 | 17 | read(fd, current_time, sizeof(current_time)); 18 | printf("%s", current_time); 19 | lock_opeartion(fd, F_UNLCK); 20 | } 21 | 22 | 23 | return 0; 24 | } 25 | 26 | void lock_opeartion(int fd, int flag){ 27 | struct flock lockinfo; 28 | 29 | lockinfo.l_type = flag; 30 | lockinfo.l_pid = getpid(); 31 | lockinfo.l_start = 0; 32 | lockinfo.l_whence = SEEK_SET; 33 | lockinfo.l_len = 0; 34 | 35 | fcntl(fd, F_SETLKW, &lockinfo); 36 | 37 | } -------------------------------------------------------------------------------- /chapter15/lock_server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void lock_opeartion(int, int); 7 | 8 | int main(int argc, char*argv[]){ 9 | 10 | time_t now; 11 | int fd = 0; 12 | char *current_time; 13 | 14 | fd = open("test.txt", O_CREAT|O_WRONLY, 0644); 15 | 16 | while(1){ 17 | time(&now); 18 | current_time = ctime(&now); 19 | lock_opeartion(fd, F_WRLCK); 20 | 21 | write(fd, current_time, strlen(current_time)); 22 | 23 | lock_opeartion(fd, F_UNLCK); 24 | } 25 | 26 | 27 | return 0; 28 | } 29 | 30 | void lock_opeartion(int fd, int flag){ 31 | struct flock lockinfo; 32 | 33 | lockinfo.l_type = flag; 34 | lockinfo.l_pid = getpid(); 35 | lockinfo.l_start = 0; 36 | lockinfo.l_whence = SEEK_SET; 37 | lockinfo.l_len = 0; 38 | 39 | fcntl(fd, F_SETLKW, &lockinfo); 40 | 41 | } -------------------------------------------------------------------------------- /chapter15/select.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define BUFFER_SIZE 1024 10 | #define oops(m, x) {perror(m); exit(x);} 11 | 12 | void show_data(int fd); 13 | 14 | int main(int argc, char *argv[]){ 15 | int fd1, fd2; //两个文件描述符 16 | fd_set read_fds; //select的read参数 17 | struct timeval timeout; //超时设置 18 | int maxfd; 19 | int retval; 20 | 21 | if( (fd1 = open(argv[1], O_RDONLY)) == -1) 22 | oops("open", -1); 23 | 24 | if( (fd2 = open(argv[2], O_RDONLY)) == -1) 25 | oops("open", -1); 26 | maxfd = (fd1 > fd2) ? fd1 : fd2; 27 | maxfd++; 28 | 29 | while(1){ 30 | FD_ZERO(&read_fds); 31 | FD_SET(fd1, &read_fds); 32 | FD_SET(fd2, &read_fds); 33 | 34 | timeout.tv_sec = atoi(argv[3]); 35 | timeout.tv_usec = 0; 36 | 37 | retval = select(maxfd, &read_fds, NULL, NULL, &timeout); 38 | if(retval == -1) 39 | oops("select", -1); 40 | 41 | if(retval > 0){ 42 | if(FD_ISSET(fd1, &read_fds)) 43 | show_data(fd1); 44 | if(FD_ISSET(fd2, &read_fds)) 45 | show_data(fd2); 46 | }else{ 47 | //超时 48 | printf("time out......\n"); 49 | } 50 | 51 | } 52 | return 0; 53 | } 54 | 55 | 56 | void show_data(int fd){ 57 | 58 | int len; 59 | char buffer[BUFFER_SIZE]; 60 | memset(buffer, 0, BUFFER_SIZE); 61 | 62 | len = read(fd, buffer, BUFFER_SIZE); 63 | if( len == -1 ) 64 | oops("read", -1); 65 | 66 | write(1, buffer, len); 67 | write(1, "\n", 1); 68 | 69 | } -------------------------------------------------------------------------------- /chapter15/shmget_client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define KEY 100 9 | #define SEG_SIZE ((size_t)100) 10 | #define BUFFER_SIZE 1024 11 | 12 | #define oops(m, x) {perror(m); exit(x);} 13 | 14 | int main(int argc, char *argv[]){ 15 | int seg_id; 16 | char *seg_mem; 17 | char my_time[BUFFER_SIZE]; 18 | 19 | //建立对象 20 | if( (seg_id = shmget(KEY, SEG_SIZE, IPC_CREAT|0777)) == -1) 21 | oops("shmget", -1); 22 | 23 | //建立内存 24 | if( (seg_mem = shmat(seg_id, NULL, 0)) == (void *)-1 ) 25 | oops("shmat", -1); 26 | 27 | //读取内容 28 | strcpy(my_time, seg_mem); 29 | 30 | printf("%s\n", my_time); 31 | 32 | 33 | return 0; 34 | } -------------------------------------------------------------------------------- /chapter15/shmget_server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define KEY 100 9 | #define SEG_SIZE ((size_t)100) 10 | 11 | #define oops(m, x) {perror(m); exit(x);} 12 | 13 | int main(int argc, char *argv[]){ 14 | int seg_id; 15 | char *seg_mem; 16 | time_t my_time; 17 | 18 | //建立对象 19 | if ( (seg_id = shmget(KEY, SEG_SIZE, IPC_CREAT|0777)) == -1) 20 | oops("shmget", -1); 21 | 22 | //分配内存 23 | if( (seg_mem = shmat(seg_id, NULL, 0)) == (void *)-1) 24 | oops("shmat", -1); 25 | 26 | time(&my_time); //获取时间 27 | strcpy(seg_mem, ctime(&my_time)); 28 | 29 | while(1); 30 | 31 | shmctl(seg_id, IPC_RMID, NULL);//删除 32 | 33 | return 0; 34 | } -------------------------------------------------------------------------------- /chapter2/my_cp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define BUFFER_SIZE 512 7 | 8 | int main(int argc, char *argv[]){ 9 | 10 | int pf_sou, pf_des; //源文件,目标文件 11 | char buffer[BUFFER_SIZE]; //缓冲区 12 | int read_num; //已读取的字节数 13 | 14 | if(argc != 3){ 15 | printf("参数不够!\n"); 16 | exit(1); 17 | } 18 | 19 | if( (pf_sou = open(argv[1], O_RDONLY)) == -1 ){ 20 | perror(argv[1]); 21 | exit(1); 22 | } 23 | 24 | if( (pf_des = creat(argv[2], 0755)) == -1 ){ 25 | perror(argv[2]); 26 | exit(1); 27 | } 28 | 29 | while( (read_num = read(pf_sou, buffer, BUFFER_SIZE)) >0){ 30 | if(write(pf_des, buffer, read_num) != read_num){ 31 | perror("write error "); 32 | exit(1); 33 | } 34 | } 35 | 36 | if(read_num == -1){ 37 | perror("read error "); 38 | exit(1); 39 | } 40 | 41 | close(pf_sou); 42 | close(pf_des); 43 | 44 | 45 | return 0; 46 | } -------------------------------------------------------------------------------- /chapter2/my_who.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define RECORD_NUM 5 9 | #define RECORD_BUF (sizeof(struct utmp)) 10 | 11 | void show_info(struct utmp *record_buffer); 12 | void show_time(long timeval); 13 | struct utmp *get_next_record(void); //获取下一个记录 14 | 15 | int pf_utmp; //文件指针 16 | 17 | char record_buffer[RECORD_NUM * RECORD_BUF]; //10个数据的总大小 18 | 19 | int current_num=0; //从文件中读了多少个数据过来,可能不到10个 20 | int read_num=0; //当前已经读到第几个数据了 21 | int flag = 0; //是否把文件内容读完了 22 | 23 | int main(void){ 24 | 25 | struct utmp *record; 26 | 27 | //打开文件 28 | if( (pf_utmp = open(UTMP_FILE, O_RDONLY)) == -1 ){ 29 | perror(UTMP_FILE); 30 | exit(1); 31 | } 32 | 33 | //while(read(pf_utmp, &record_buffer, record_size)) 34 | // show_info(&record_buffer); 35 | 36 | while( (record = get_next_record()) != NULL){ 37 | show_info(record); 38 | } 39 | 40 | close(pf_utmp); //关闭指针 41 | 42 | return 0; 43 | } 44 | 45 | void show_info(struct utmp *record_buffer){ 46 | if(record_buffer->ut_type != USER_PROCESS) //这条信息如果不是已经登录用户,就退出 47 | return; 48 | 49 | printf("%s\t", record_buffer->ut_user); //登录账户 50 | printf("%s\t", record_buffer->ut_line); //tty 51 | show_time(record_buffer->ut_time); //时间 52 | } 53 | 54 | void show_time(long timeval){ 55 | char *cp; 56 | cp = ctime(&timeval); 57 | printf("%s", cp); //时间后面有一个回车 58 | } 59 | 60 | struct utmp *get_next_record(){ 61 | struct utmp *utmp_buffer; 62 | 63 | if(current_num == read_num && flag) 64 | return NULL; 65 | 66 | //当读完了缓存中的5个数后再读取 67 | if(current_num == read_num){ 68 | int size = read(pf_utmp, record_buffer, RECORD_NUM * RECORD_BUF); //读取5个数据 69 | current_num = size / RECORD_BUF; //里面真正读了有多少个数 70 | if(current_num < 5) //不足10个,说明已经读完了 71 | flag = 1; 72 | if(current_num == 0) //没有数据直接退出 73 | return NULL; 74 | 75 | read_num = 0; //置0 76 | } 77 | 78 | utmp_buffer = (struct utmp*)&record_buffer[read_num * RECORD_BUF]; 79 | read_num++; 80 | return utmp_buffer; //返回当前读取的数值 81 | 82 | } 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /chapter3/my_ls.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include //getpwuid 7 | #include //getgrgid 8 | #include //ctime 9 | #include 10 | 11 | void ls_info(char *dirname); 12 | 13 | char *show_mode(int mode); //mode 14 | char *show_uid(int uid); //uid 15 | char *show_gid(int gid); //gid 16 | 17 | int main(int argc, char *argv[]){ 18 | int num = argc-1; 19 | if(argc == 1) 20 | ls_info("."); 21 | else{ 22 | while(num){ 23 | printf("%s:\n", argv[num]); 24 | ls_info(argv[num--]); 25 | } 26 | 27 | } 28 | 29 | return 0; 30 | } 31 | 32 | void ls_info(char *dirname){ 33 | 34 | DIR *pd; //目录 35 | struct dirent *dir_info; //目录结构体 36 | struct stat file_stat; //文件的属性结构体 37 | 38 | //打开目录 39 | if( (pd = opendir(dirname)) == NULL){ 40 | perror(dirname); 41 | } 42 | 43 | //读取目录内容 44 | while( (dir_info=readdir(pd)) != NULL){ 45 | //printf("%s\n", dir_info->d_name); 46 | //过滤 47 | if( (strcmp(dir_info->d_name, ".") == 0) || (strcmp(dir_info->d_name, "..") == 0) ) 48 | continue; 49 | 50 | //获取属性 51 | 52 | char str[100]; 53 | sprintf(str, "%s/%s", dirname, dir_info->d_name); 54 | //注意文件路径!!!! 55 | if(stat(str, &file_stat) == -1){ 56 | perror(dir_info->d_name); 57 | exit(1); 58 | }else{ 59 | printf("%s ", show_mode(file_stat.st_mode)); //mode 60 | printf("%-4d ", file_stat.st_nlink); //hard link 61 | printf("%-10s", show_uid(file_stat.st_uid)); //UID 62 | printf("%-10s", show_gid(file_stat.st_gid)); //GID 63 | printf("%-8ld ", file_stat.st_size); //size 64 | printf("%.12s ", 4+ctime(&file_stat.st_mtime)); //mtime,%m.ns 输出占m列,但只取字符串中左端n个字符。这n个字符输出在m列的右侧,左补空格 65 | printf("%s\n", dir_info->d_name); //name 66 | } 67 | 68 | } 69 | 70 | //关闭目录 71 | closedir(pd); 72 | } 73 | 74 | char *show_mode (int mode){ 75 | static char str[10]; 76 | 77 | strcpy(str, "----------"); //重置。不然会和上次一样 78 | if(S_ISDIR(mode)) str[0] = 'd'; 79 | if(S_ISCHR(mode)) str[0] = 'c'; 80 | if(S_ISBLK(mode)) str[0] = 'b'; 81 | if(S_ISFIFO(mode)) str[0] = 'p'; 82 | if(S_ISLNK(mode)) str[0] = 'l'; 83 | 84 | if(S_IRUSR & mode) str[1] = 'r'; 85 | if(S_IWUSR & mode) str[2] = 'w'; 86 | if(S_IXUSR & mode) str[3] = 'x'; 87 | 88 | if(S_IRGRP & mode) str[4] = 'r'; 89 | if(S_IWGRP & mode) str[5] = 'w'; 90 | if(S_IXGRP & mode) str[6] = 'x'; 91 | 92 | if(S_IROTH & mode) str[7] = 'r'; 93 | if(S_IWOTH & mode) str[8] = 'w'; 94 | if(S_IXOTH & mode) str[9] = 'x'; 95 | 96 | if(S_ISUID & mode) str[1] = 's'; 97 | if(S_ISGID & mode) str[5] = 's'; 98 | if(S_ISVTX & mode) str[9] = 't'; 99 | 100 | return str; 101 | } 102 | 103 | char* show_uid(int uid){ 104 | struct passwd *username; 105 | static char str[10]; //设置静态变量,不然会被提示返回局部变量地址 106 | 107 | if((username = getpwuid(uid)) == NULL){ //搜索passwd没有找到就返回UID 108 | sprintf(str, "%s", uid); 109 | return str; 110 | } 111 | 112 | return username->pw_name; 113 | } 114 | 115 | char* show_gid(int gid){ 116 | struct group *groupname; 117 | static char str[10]; 118 | 119 | if((groupname = getgrgid(gid)) == NULL){ //搜索group没有找到就返回GID 120 | sprintf(str, "%s", gid); 121 | return str; 122 | } 123 | 124 | return groupname->gr_name; 125 | } 126 | 127 | 128 | -------------------------------------------------------------------------------- /chapter4/my_pwd.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define BUFFER_SIZE 512 9 | 10 | void pwd(char *filename); 11 | char *inode_to_dirname(ino_t inode); 12 | ino_t get_inode(char *filename); 13 | 14 | char dir_path[BUFFER_SIZE]=""; 15 | 16 | int main(int argc, int *argv[]){ 17 | 18 | int path_len = 0; 19 | 20 | pwd("."); 21 | 22 | //下面只是为了将最后面的"/"删除 23 | path_len = strlen(dir_path); 24 | dir_path[path_len-1] = '\0'; 25 | 26 | printf("%s\n", dir_path); 27 | 28 | return 0; 29 | } 30 | 31 | void pwd(char *filename){ 32 | 33 | ino_t current_inode; 34 | current_inode = get_inode("."); 35 | 36 | //char str[BUFFER_SIZE]=""; 37 | char dir_temp[BUFFER_SIZE]=""; 38 | 39 | strcpy(dir_temp, dir_path); //把路径赋值下来方便下面输出 40 | 41 | if(get_inode("..") == current_inode){ 42 | sprintf(dir_path, "/%s", dir_temp); 43 | return; 44 | }else{ 45 | chdir(".."); 46 | 47 | //sprintf(st, "%s", inode_to_dirname(current_inode)); 48 | //printf("%s\n", st); 49 | 50 | //如果把dir_temp换为dir_path,你会发现那两个%s会一样,因为dir_path先被赋值了,然后又被自己赋值了一次 51 | sprintf(dir_path, "%s/%s", inode_to_dirname(current_inode), dir_temp); 52 | pwd("."); 53 | } 54 | } 55 | 56 | //返回文件的inode号,只在文件在当前目录下有效 57 | ino_t get_inode(char *filename){ 58 | struct stat current_dir_stat; //获取当前目录中“.”的inode号 59 | 60 | //打开当前filename所在目录 61 | if(stat(filename, ¤t_dir_stat) == -1){ 62 | perror(filename); 63 | exit(1); 64 | } 65 | 66 | return current_dir_stat.st_ino; 67 | } 68 | 69 | //打开当前目录,查看当前目录下是否有和参数inode相同的文件,如果有返回dirname 70 | char *inode_to_dirname(ino_t inode){ 71 | 72 | DIR *current_dir; // 打开当前目录 73 | struct dirent *current_dir_info; // 当前目录的信息 74 | 75 | //打开当前目录 76 | if( (current_dir = opendir(".")) == NULL){ 77 | perror("."); 78 | exit(1); 79 | } 80 | 81 | //获取父目录的inode号 82 | while((current_dir_info = readdir(current_dir)) != NULL){ 83 | if( current_dir_info->d_ino == inode ){ 84 | close(current_dir); 85 | return current_dir_info->d_name; //返回filename 86 | 87 | } 88 | } 89 | 90 | //获取inode失败 91 | if(current_dir_info == NULL){ 92 | perror("."); 93 | exit(2); 94 | } 95 | } -------------------------------------------------------------------------------- /chapter5/echo_stat.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | int main(int argc, char *argv[]){ 8 | 9 | struct termios stty_info; 10 | 11 | if((tcgetattr(0, &stty_info)) == -1){ 12 | perror("tcgetattr:"); 13 | exit(1); 14 | } 15 | 16 | if( stty_info.c_lflag & ECHO) 17 | printf("ECHO : NO\n"); 18 | else 19 | printf("ECHO : OFF\n"); 20 | 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /chapter5/my_stty.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | int main() 7 | { 8 | struct termios ttyinfo; 9 | 10 | if ( tcgetattr( 0 , &ttyinfo ) == -1 ){ 11 | perror( "cannot get params about stdin"); 12 | exit(1); 13 | } 14 | 15 | showbaud ( cfgetospeed( &ttyinfo ) ); 16 | 17 | printf("VINTER = ^%c\t", ttyinfo.c_cc[VINTR] - 1 + 'A'); 18 | printf("VQUIT = ^%c\t", ttyinfo.c_cc[VQUIT]- 1 + 'A'); 19 | printf("VERASE = ^%c\t", '?'); 20 | printf("VKILL = ^%c\t\n", ttyinfo.c_cc[VKILL]- 1 + 'A'); 21 | printf("VEOF = ^%c\t", ttyinfo.c_cc[VEOF]- 1 + 'A'); 22 | printf("VMIN = ^%c\t", ttyinfo.c_cc[VMIN]- 1 + 'A'); 23 | printf("VEOL = ^%c\t", ttyinfo.c_cc[VEOL]- 1 + 'A'); 24 | printf("VTIME = ^%c\t\n", ttyinfo.c_cc[VTIME]- 1 + 'A'); 25 | 26 | 27 | show_some_flags( &ttyinfo ); 28 | 29 | return 0; 30 | } 31 | 32 | int showbaud( int thespeed ){ 33 | printf("spend "); 34 | switch ( thespeed ){ 35 | case B300: printf("300\n"); break; 36 | case B600: printf("600\n"); break; 37 | case B1200: printf("1200\n"); break; 38 | case B1800: printf("1800\n"); break; 39 | case B2400: printf("2400\n"); break; 40 | case B4800: printf("4800\n"); break; 41 | case B9600: printf("9600\n"); break; 42 | case B19200: printf("19200\n"); break; 43 | case B38400: printf("38400\n"); break; 44 | default: printf("Fast\n"); break; 45 | } 46 | } 47 | 48 | struct flaginfo { int fl_value; char *fl_name; }; 49 | 50 | struct flaginfo input_flags[] = { 51 | IGNBRK , "Ignore break condition", 52 | BRKINT , "Signal interrupt on break", 53 | IGNPAR , "Ignore chars with parity errors", 54 | PARMRK , "Mark parity errors", 55 | INPCK , "Enable input parity check", 56 | ISTRIP , "Strip character", 57 | INLCR , "Map NL to CR on input", 58 | IGNCR , "Ignore CR", 59 | ICRNL , "Map CR to NL on input", 60 | IXON , "Enable start/stop output control", 61 | IXOFF , "Enable start/stop input control", 62 | 0 , NULL }; 63 | 64 | struct flaginfo output_flags[] = { 65 | OPOST , "Post-process output", 66 | ONLCR , "Map NL to CR-NL on output", 67 | OCRNL , "Map CR to NL on output", 68 | OFILL , "Use fill characters for delay", 69 | NLDLY , "Select newline delays", 70 | CRDLY , "Select carriage-return delays", 71 | TABDLY , "Select horizontal-tab delays", 72 | BSDLY , "Select backspace delays:", 73 | FFDLY , "Select form-feed delays", 74 | VTDLY , "Select vertical-tab delays", 75 | 0 , NULL }; 76 | 77 | 78 | struct flaginfo c_flags[] = { 79 | CSIZE , "Character size", 80 | CSTOPB , "Send two stop bits, else one", 81 | CREAD , "Enable receiver", 82 | PARENB , "Parity enable", 83 | PARODD , "Odd parity, else even", 84 | HUPCL , "Hang up on last close", 85 | CLOCAL , "Ignore modem status lines", 86 | 0 , NULL }; 87 | 88 | 89 | struct flaginfo local_flags[] = { 90 | ISIG , "Enable signals", 91 | ICANON , "Canonical input (erase and kill)", 92 | ECHO , "Enable echo", 93 | ECHOE , "Echo ERASE as BS-SPACE-BS", 94 | ECHOK , "Echo KILL by starting new line", 95 | 0 , NULL }; 96 | 97 | 98 | int show_some_flags( struct termios *ttyp ){ 99 | printf("c_iflag: \n"); 100 | show_flagset( ttyp->c_iflag, input_flags ); 101 | 102 | printf("c_oflag: \n"); 103 | show_flagset( ttyp->c_oflag, output_flags ); 104 | 105 | printf("c_cflag: \n"); 106 | show_flagset( ttyp->c_cflag, c_flags ); 107 | 108 | printf("c_lflag: \n"); 109 | show_flagset( ttyp->c_lflag, local_flags ); 110 | } 111 | 112 | int show_flagset( int thevalue, struct flaginfo thebitnames[] ){ 113 | int i; 114 | 115 | for ( i=0; thebitnames[i].fl_value ; i++ ) { 116 | printf( " %s is ", thebitnames[i].fl_name); 117 | if ( thevalue & thebitnames[i].fl_value ) 118 | printf("ON\n"); 119 | else 120 | printf("OFF\n"); 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /chapter5/my_write.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define BUFFER_SIZE 512 8 | 9 | //向终端发送消息,不是向某人发送消息 10 | int main(int argc, char *argv[]){ 11 | 12 | int p_dev; 13 | char send_buffer[BUFFER_SIZE]; 14 | 15 | if(argc != 2){ 16 | printf("参数错误!"); 17 | exit(1); 18 | } 19 | 20 | if( (p_dev = open(argv[1], O_WRONLY)) == -1){ 21 | perror(argv[1]); 22 | exit(1); 23 | } 24 | 25 | //EOF也可以退出 26 | while(fgets(send_buffer, BUFFER_SIZE, stdin) != NULL){ 27 | if(write(p_dev, send_buffer, strlen(send_buffer)) != strlen(send_buffer)){ 28 | perror("send:"); 29 | } 30 | } 31 | 32 | close(p_dev); 33 | return 0; 34 | } -------------------------------------------------------------------------------- /chapter5/set_stat.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | int main(int argc, char *argv[]){ 8 | 9 | struct termios stty_info; 10 | 11 | if(argc != 2){ 12 | printf("参数错误!\n"); 13 | } 14 | 15 | if((tcgetattr(0, &stty_info)) == -1){ 16 | perror("tcgetattr:"); 17 | exit(1); 18 | } 19 | 20 | if(argv[1][0] == 'y' || argv[1][0] == 'Y'){ 21 | stty_info.c_lflag |= ECHO; 22 | } 23 | 24 | if(argv[1][0] == 'n' || argv[1][0] == 'N'){ 25 | stty_info.c_lflag &= ~ECHO; 26 | } 27 | 28 | if((tcsetattr(0, TCSANOW, &stty_info)) == -1){ 29 | perror("tcsetattr:"); 30 | exit(1); 31 | } 32 | 33 | return 0; 34 | } -------------------------------------------------------------------------------- /chapter6/my_play.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define SELLPTIME 2 9 | 10 | int get_resopnse(void); 11 | void save_stty(void); //保存终端属性 12 | void renew_stty(void); //回复终端属性 13 | void set_stty(void); //设置非规范模式和单字符输入 14 | void set_flags(void); //设置非阻塞 15 | void ctrl_c_init(int); //CTRL+C 16 | 17 | static struct termios stty_info_buffer; 18 | static flags; 19 | 20 | int main(int argc, char *argv[]){ 21 | 22 | int answer=2; //0:no, 1:yes,2:没选择 23 | 24 | save_stty(); //保存终端属性 25 | set_stty(); //设置当前环境的终端属性 26 | set_flags(); //设置非阻塞 27 | signal(SIGINT, ctrl_c_init); //CTRL+C 28 | signal(SIGQUIT, SIG_IGN); //忽略CTRL_\ 29 | 30 | answer = get_resopnse(); 31 | 32 | if(answer == 1) 33 | printf("YES\n"); 34 | if(answer == 0) 35 | printf("NO\n"); 36 | if(answer == 2) 37 | printf("NOT CHOOSE\n"); 38 | 39 | renew_stty(); //恢复磁盘属性 40 | return 0; 41 | } 42 | 43 | int get_resopnse(void){ 44 | int num = 3; //有3次输入的机会 45 | char answer; 46 | 47 | printf("%s: ", "Do you want to go dead?"); 48 | fflush(stdout); //强制把输出缓冲区的数据输出 49 | 50 | while(num > 0){ 51 | sleep(SELLPTIME); //睡眠2秒,期间如果没输入则继续睡两秒 52 | answer = getchar(); //因为是非阻塞,所以没有数据会直接跳过 53 | switch(answer){ 54 | case 'y': 55 | case 'Y': return 1; 56 | case 'n': 57 | case 'N': return 0; 58 | } 59 | putchar('\a'); 60 | num--; 61 | } 62 | 63 | return 2; 64 | } 65 | 66 | void save_stty(void){ 67 | flags = fcntl(0, F_GETFL); //获取磁盘属性 68 | tcgetattr(0, &stty_info_buffer); //把设备终端保存下来以便恢复 69 | } 70 | 71 | void renew_stty(void){ 72 | tcsetattr(0, TCSANOW, &stty_info_buffer); //恢复 73 | fcntl(0, F_SETFL, flags);//恢复磁盘属性 74 | } 75 | 76 | void set_stty(void){ 77 | struct termios stty_info; 78 | tcgetattr(0, &stty_info); 79 | stty_info.c_lflag &= ~ICANON; //关闭规范模式 80 | stty_info.c_cc[VMIN] = 1; //设单字符模式,一个字符一个字符输入 81 | stty_info.c_lflag &= ~ECHO; //关闭回显 82 | tcsetattr(0, TCSANOW, &stty_info); 83 | } 84 | 85 | void set_flags(void){ 86 | int flags; 87 | flags = fcntl(0, F_GETFL); 88 | flags |= O_NDELAY; //关闭阻塞 89 | fcntl(0, F_SETFL, flags); 90 | } 91 | 92 | void ctrl_c_init(int signum){ 93 | renew_stty(); 94 | exit(1); 95 | } 96 | 97 | -------------------------------------------------------------------------------- /chapter7/my_timer.c: -------------------------------------------------------------------------------- 1 | /******* 2 | **定时器 3 | **参数两个(毫秒):开始时间,间隔时间 4 | **定时完毕输出“timer over!” 5 | *******/ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | void set_timer(int start_time, int interval_time); 13 | void timer_fuc(int signum); 14 | 15 | int main(int argc, char *argv[]){ 16 | 17 | if(argc != 3){ 18 | printf("参数错误\n"); 19 | } 20 | 21 | set_timer( atoi(argv[1]), atoi(argv[2])); 22 | while(1) 23 | pause(); 24 | return 0; 25 | } 26 | 27 | 28 | void set_timer(int start_time, int interval_time){ 29 | signal(SIGALRM, timer_fuc); 30 | 31 | struct itimerval new_timer; 32 | int start_sec=0, start_usec=0; 33 | int interval_sec=0, interval_usec=0; 34 | 35 | start_sec = start_time / 1000; //秒 36 | start_usec = (start_time % 1000) * 1000L; //毫秒 37 | 38 | new_timer.it_value.tv_sec = start_sec; 39 | new_timer.it_value.tv_usec = start_usec; 40 | 41 | interval_sec = interval_time / 1000; //秒 42 | interval_usec = (interval_time % 1000) * 1000L; //毫秒 43 | 44 | new_timer.it_interval.tv_sec = interval_sec; 45 | new_timer.it_interval.tv_usec = interval_usec; 46 | 47 | setitimer(ITIMER_REAL, &new_timer, NULL); 48 | } 49 | 50 | 51 | void timer_fuc(int signum){ 52 | 53 | printf("timer over!\n"); 54 | } -------------------------------------------------------------------------------- /chapter8/my_shell.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define ARGLIST_NUM 10 //参数个数 7 | #define ARG_LEN 100 //每个参数长度 8 | 9 | void exec(char *arglist[]); 10 | 11 | 12 | int main(int argc, char *argv[]){ 13 | 14 | char *arglist[ARGLIST_NUM]; //参数列表,注意这里没分配内存 15 | char arg_buffer[ARG_LEN]; //元素缓存 16 | int i=0, j=0; 17 | //get_arglist(arglist); 18 | 19 | 20 | //循环获取参数 21 | while(i < ARGLIST_NUM){ 22 | 23 | printf("arg[%d]: ", i); 24 | 25 | fgets(arg_buffer, ARG_LEN, stdin); //arglist没有分配内存不能直接赋值 26 | 27 | if( strcmp(arg_buffer, "\n") == 0 ){ 28 | arglist[i] == NULL; 29 | exec(arglist); 30 | 31 | //释放空间 32 | for(j=0; j 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #define ARGLIST_NUM 10 //参数个数 13 | #define ARG_LEN 100 //每个参数长度 14 | 15 | #define BUFFER_SIZE 10 //命令行大小 16 | #define ADD_BUFFER_SIZE 5 //命令行不够再加5 17 | 18 | void exec(char *arglist[]); //执行程序 19 | char *get_cmd(void); //获取一整条命令,包括参数 20 | char **get_arglist(char *current_cmd); //把命名拆分成到arglist数组中 21 | 22 | int main(int argc, char *argv[]){ 23 | 24 | char *current_cmd; //存储输入的每条命令 25 | char **arglist; //参数列表,注意这里没分配内存 26 | 27 | int i=0; 28 | 29 | //忽略信号 30 | signal(SIGINT, SIG_IGN); 31 | signal(SIGQUIT, SIG_IGN); 32 | 33 | while( (current_cmd = get_cmd() ) != NULL){ 34 | if( strcmp(current_cmd, "") == 0) 35 | continue; 36 | 37 | arglist = get_arglist(current_cmd); //获取参数数组 38 | 39 | //while(arglist[i] != NULL) 40 | // printf("%s\n", arglist[i++]); 41 | 42 | //执行程序 43 | exec(arglist); 44 | 45 | //释放空间 46 | while(arglist[i] != NULL) 47 | free(arglist[i++]); 48 | } 49 | 50 | return 0; 51 | } 52 | 53 | char **get_arglist(char *current_cmd){ 54 | static char *arglist[ARGLIST_NUM]; //要返回的字符串数组 55 | char arg_buffer[ARG_LEN]; //缓存每个元素 56 | char *cmd_buffer; //把命令复制到这里 57 | int i=0, arg_num=0; 58 | 59 | //分配空间,并赋值命令 60 | cmd_buffer=malloc(strlen(current_cmd)); 61 | strcpy(cmd_buffer, current_cmd); 62 | //printf("%s", cmd_buffer); 63 | //list -a -l 64 | while(1){ 65 | if(cmd_buffer[i] == ' ' || cmd_buffer[i] == '\0'){ 66 | arglist[arg_num] = malloc(i+1); //分配 67 | strncpy(arglist[arg_num], cmd_buffer, i); //赋值 68 | arglist[arg_num][i] = '\0'; //添加'\0' 69 | 70 | // printf("%s\n", arglist[arg_num]); 71 | if(cmd_buffer[i] == '\0'){ 72 | arglist[arg_num+1] = NULL; 73 | return arglist; 74 | } 75 | 76 | 77 | cmd_buffer = cmd_buffer+i+1; //把指针移到空格后面那一字节 78 | arg_num++; 79 | i=0; 80 | } 81 | i++; 82 | } 83 | 84 | } 85 | 86 | 87 | char *get_cmd(void){ 88 | char *currnet_cmd; 89 | 90 | int buffer_flag = BUFFER_SIZE; //用来重新分配内存 91 | int c_num = 0; //已输入字符数的数量 92 | char c; //缓存输入字符 93 | 94 | currnet_cmd = malloc(BUFFER_SIZE); //先分配一个小内存,10个字符 95 | 96 | printf("[SKING_SHELL] "); 97 | 98 | while( (c = fgetc(stdin)) != EOF){ 99 | 100 | //如果是回车则直接退出子程序 101 | if(c == '\n'){ 102 | currnet_cmd[c_num] = '\0'; 103 | return currnet_cmd; 104 | } 105 | 106 | currnet_cmd[c_num++] = c; 107 | 108 | //重新分配内存 109 | if( ((c_num - BUFFER_SIZE) % ADD_BUFFER_SIZE) == 0){ 110 | currnet_cmd = realloc(currnet_cmd, buffer_flag+ADD_BUFFER_SIZE); 111 | buffer_flag += ADD_BUFFER_SIZE; 112 | } 113 | 114 | } 115 | 116 | return NULL; 117 | } 118 | 119 | void exec(char *arglist[]){ 120 | 121 | int ret_pid = 0; //子进程PID 122 | int ret_val = 0; //子进程exit返回值 123 | 124 | ret_pid = fork(); //开启新进程 125 | switch(ret_pid){ 126 | case 0: //子进程执行程序 127 | if( execvp(arglist[0], arglist) == -1){ 128 | perror(arglist[0]); 129 | exit(2); 130 | } 131 | _exit(1); 132 | 133 | case -1: //错误 134 | perror("fork failed!"); 135 | exit(1); 136 | 137 | default: //父进程 138 | while(ret_pid != wait(&ret_val)); //死循环等待子进程结束 139 | } 140 | 141 | } 142 | --------------------------------------------------------------------------------