开始学习Unix环境高级编程(第三版;中文版)

配置开发环境

  本文所用操作系统:Win10 x64位下VMware15虚拟机Ubuntu 20.10镜像。通过apt命令来获取gcc编译器等等开发工具,使用vim时可以在~/.vimrc文件中自定义文本编辑器风格,建议直接抄网上作业。本文所使用风格:

 1 set nu
 2 syntax on
 3 set guifont=DejaVu\ Sans\ Mono\ 12
 4 set softtabstop=4
 5 set shiftwidth=4
 6 set expandtab
 7 set guioptions-=T
 8 set nobackup
 9 set formatoptions=tcrqn
10 set cindent
11 set smartindent
12 set incsearch
13 set autoindent
14 set encoding=utf-8
15 set fileencodings=ucs-bom,utf-8,gb2312,gb18030,gbk,cp936,latin1,chinese,unicode
16 
17 
18 set modifiable 
19 
20 let mapleader='\' 
21 nmap <leader>f :!youdao <C-R>=expand("<cword>")<CR><CR>
22 
23 command -nargs=1 FY  : !youdao <args>   
24 
25 
26 "<CR>:copen<CR>
27 
28 ":copen <CR>   :copen  :set modifiable 
29 "Show matching bracets
30 set showmatch
31 "
32 ""Get out of VI's compatible mode
33 set nocompatible
34 
35 if has("cscope")
36     set csprg=/usr/bin/cscope
37     set csto=0
38     set cst
39     set nocsverb
40     " add any database in current directory
41          if filereadable("cscope.out")
42              cs add cscope.out
43     "             " else add database pointed to by
44     "             environment
45                      elseif $CSCOPE_DB != ""
46     cs add $CSCOPE_DB
47 endif
48 set csverb
49 set cscopetag
50 set cscopequickfix=s-,g-,c-,d-,t-,e-,f-,i-
51 nmap <C-c><C-s> :cs find s <C-R>=expand("<cword>")<CR><CR>
52 nmap <C-c><C-g> :cs find g <C-R>=expand("<cword>")<CR><CR>
53 nmap <C-c><C-c> :cs find c <C-R>=expand("<cword>")<CR><CR>
54 nmap <C-c><C-t> :cs find t <C-R>=expand("<cword>")<CR><CR>
55 nmap <C-c><C-e> :cs find e <C-R>=expand("<cword>")<CR><CR>
56 nmap <C-c><C-f> :cs find f <C-R>=expand("<cfile>")<CR><CR>
57 nmap <C-c><C-i> :cs find i <C-R>=expand("<cfile>")<CR><CR>
58 nmap <C-c><C-d> :cs find d <C-R>=expand("<cword>")<CR><CR>
59 endif
60 
61 "Have the mouse enabled all the time
62 "set mouse=a
63 "
64 ""Set to auto read when a file is changed from the outside
65 set autoread
66 
67 "Enable filetype plugin
68 filetype plugin indent on
69 colo desert
70 set hlsearch
71 
72 "let Tlist_Ctags_Cmd = '/usr/bin/ctags-exuberant' 
73 
74 nnoremap <silent> <F9> :TlistToggle<CR>
75 "let Tlist_Use_Right_Window=1
76 colorscheme delek 
77 "colorscheme evening
78 set ruler
79 hi Special ctermfg = red

  最后建立共享文件夹,使用VMware tools。


 

创建工作目录

  本书所有例程均使用了“apue.h”头文件,该文件及相关内容作者在附录B中已给出,建议自己打出来加深印象。apue 即是 Advanced Programming in the UNIX Environment。但是有些印刷错误,目前已发现:

1:722页 int send_err(int, int, const char *); 这里 const 印成了 onst;

2:724页 /* ISO C variable arguments */ 这里 arguments 印成了aruments;

3:725页 * Error code passed as explicit parameter. 这里 explicit 印成了explict,本页下方还有一处同样的错误;

4:727页 static void log_doit(int, int, int, const char * va_list); 这里 va_list 后面多了 ap 。

  后面的两个是出错函数的实现 .c 文件,作者没有给出建议的文件名,我们既可以自己起名,也可以将它们直接与 apue.h 整合在一起。本文所用文件名:output_to_stderr.c 和 daemon_errfunc.c 。建议创建目录:mkdir apue_learning,将 apue.h 和 两个出错函数实现文件放入,学习到每一章的时候创建那一章的目录,例如:chapter_01。这样一来包含 apue.h 文件时需要 #include "../apue",编译时需要注意带上两个 .c 文件:gcc xxxx.c ../output_to_stderr.c ../daemon_errfunc.c -o xxxx,使用 tab 自动补全就好。

  若编译后出现warning: relocate against ... 最后 error: ld returned 1 exit status,这就是需要在你的程序中加上 int log_to_stderr,其实用不到守护进程的话就不用带上 daemon_errfunc.c 进行编译了,这样也不用声明 log_to_stderr 了。

  如此一来就可以顺利使用本书进行学习了。给白嫖党:

apue.h:

  1 /*
  2  * apue.h -- Header for Advanced Programming in the UNIX Environment, 
  3  * to be included before all standard system headers.
  4  */
  5 #ifndef _APUE_H
  6 #define _APUE_H
  7 
  8 #define _POSIX_C_SOURCE 200809L
  9 
 10 #if defined(SOLARIS)            /* Solaris 10 */
 11 #define _XOPEN_SOURCE 600
 12 #else
 13 #define _XOPEN_SOURCE 700
 14 #endif
 15 
 16 #include <sys/types.h>          /* some systems still require this */
 17 #include <sys/stat.h>
 18 #include <sys/termios.h>          /* for winsize */
 19 
 20 #if defined(MACOS) || !defined(TIOCGWINSZ)
 21 #include <sys/ioctl.h>
 22 #endif
 23 
 24 #include <stdio.h>              /* for convenience */
 25 #include <stdlib.h>             /* for convenience */
 26 #include <stddef.h>             /* for offsetof */
 27 #include <string.h>             /* for convenience */
 28 #include <unistd.h>             /* for convenience */
 29 #include <signal.h>             /* for SIG_ERR */
 30 
 31 #define MAXLINE 4096            /* max line length */
 32 
 33 /*
 34  * Default file access permissions for new files.
 35  */
 36 #define FILE_MODE   (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
 37 
 38 /*
 39  * Default permissions for new directories.
 40  */
 41 
 42 #define DIR_MODE    (FILE_MODE | S_IXUSR | S_IXGRP | S_IXOTH)
 43 
 44 typedef void        Sigfunc(int);/* for signal handlers */
 45 
 46 #define min(a,b)    ((a) < (b) ? (a) : (b))
 47 #define max(a,b)    ((a) > (b) ? (a) : (b))
 48 
 49 /*
 50  * Prototypes for our own functions
 51  */
 52 
 53 char    *path_alloc(size_t *);                  /* Figure 2.16 */
 54 long    open_max(void);                         /* Figure 2.17 */
 55 
 56 int     set_cloexec(int);                       /* Figure 13.9 */
 57 void    clr_fl(int, int);
 58 void    set_fl(int, int);                       /* Figure 3.12 */
 59 
 60 void    pr_exit(int);                           /* Figure 8.5 */
 61 
 62 void    pr_mask(const char *);                  /* Figure 10.14 */
 63 Sigfunc *signal_intr(int, Sigfunc *);           /* Figure 10.19 */
 64 
 65 void    daemonize(const char *);                /* Figure 13.1 */
 66 
 67 void    sleep_us(unsigned int);                 /* Exercise 14.5 */
 68 ssize_t readn(int, void *, size_t);             /* Figure 14.24 */
 69 ssize_t writen(int, const void *, size_t);      /* Figure 14.24 */
 70 
 71 int     fd_pipe(int *);                         /* Figure 17.2 */
 72 int     recv_fd(int, ssize_t (*func)(int,
 73                 const void *, size_t));         /* Figure 17.14 */
 74 int     send_fd(int, int);                      /* Figure 17.13 */
 75 int     send_err(int, int, const char *);       /* Figure 17.12 */
 76 int     serv_listen(const char *);              /* Figure 17.8 */
 77 int     serv_accept(int, uid_t *);              /* Figure 17.9 */
 78 int     cli_conn(const char *);                 /* Figure 17.10 */
 79 int     buf_args(char *, int (*func)(int,
 80                  char **));                     /* Figure 17.23 */
 81 
 82 int     tty_cbreak(int);                        /* Figure 18.20 */
 83 int     tty_raw(int);                           /* Figure 18.20 */
 84 int     tty_reset(int);                         /* Figure 18.20 */
 85 void    tty_atexit(void);                       /* Figure 18.20 */
 86 struct termios *tty_termios(void);              /* Figure 18.20 */
 87 
 88 int     ptym_open(char *, int);                 /* Figure 19.9 */
 89 int     ptys_open(char *);                      /* Figure 19.9 */
 90 
 91 #ifdef  TIOCGWINSZ
 92 pid_t   pty_fork(int *, char *, int, const struct termios *,
 93                  const struct winsize *);       /* Figure 19.10 */
 94 #endif
 95 
 96 int     lock_reg(int, int, int, off_t, 
 97                  int, off_t);                   /* Figure 14.5 */
 98 
 99 #define read_lock(fd, offset, whence, len) \
100             lock_reg((fd), F_SETLK, F_RDLCK, \
101                      (offset), (whence), (len))
102 #define readw_lock(fd, offset, whence, len) \
103             lock_reg((fd), F_SETLKW, F_RDLCK, \
104                      (offset), (whence), (len))
105 #define write_lock(fd, offset, whence, len) \
106             lock_reg((fd), F_SETLK, F_WRLCK, \
107                      (offset), (whence), (len))
108 #define writew_lock(fd, offset, whence, len) \
109             lock_reg((fd), F_SETLKW, F_WRLCK, \
110                      (offset), (whence), (len))
111 #define un_lock(fd, offset, whence, len) \
112             lock_reg((fd), F_SETLK, F_UNLCK, \
113                      (offset), (whence), (len))
114 
115 pid_t   lock_test(int, int, off_t, int, off_t); /* Figure 14.6 */
116 
117 #define is_read_lockable(fd, offset, whence, len) \
118             (lock_test((fd), F_RDLCK, (offset), \
119                        (whence), (len)) == 0)
120 #define is_write_lockable(fd, offset, whence, len) \
121             (lock_test((fd), F_WRLCK, (offset), \
122                        (whence), (len)) == 0)
123 
124 void    err_msg(const char *, ...);             /* Appendix B */
125 void    err_dump(const char *, ...) __attribute__((noreturn));
126 void    err_quit(const char *, ...) __attribute__((noreturn));
127 void    err_cont(int, const char *, ...);
128 void    err_exit(int, const char *, ...) __attribute__((noreturn));
129 void    err_ret(const char *, ...);
130 void    err_sys(const char *, ...) __attribute__((noreturn));
131 
132 void    log_msg(const char *, ...);             /* Appendix B */
133 void    log_open(const char *, int, int);
134 void    log_quit(const char *, ...) __attribute__((noreturn));
135 void    log_ret(const char *, ...);
136 void    log_sys(const char *, ...) __attribute__((noreturn));
137 void    log_exit(int, const char *, ...) __attribute__((noreturn));
138 
139 void    TELL_WAIT(void);        /* parent/child from Section 8.9 */
140 void    TELL_PARENT(pid_t);
141 void    TELL_CHILD(pid_t);
142 void    WAIT_PARENT(void);
143 void    WAIT_CHILD(void);
144 
145 #endif /* _APUE_H */

output_to_stderr.c:

  1 #include "apue.h"
  2 #include <errno.h>          /* for definition of errno */
  3 #include <stdarg.h>         /* ISO C variable arguments */
  4 
  5 static void err_doit(int, int, const char *, va_list);
  6 
  7 /*
  8  * Nonfatal error related to a system call.
  9  * Peint a message and return.
 10  */
 11 void
 12 err_ret(const char *fmt, ...)
 13 {
 14     va_list ap;
 15 
 16     va_start(ap, fmt);
 17     err_doit(1, errno, fmt, ap);
 18     va_end(ap);
 19 }
 20 
 21 /*
 22  * Fatal error related to a system call.
 23  * Print a message and terminate.
 24  */
 25 void
 26 err_sys(const char *fmt, ...)
 27 {
 28     va_list ap;
 29 
 30     va_start(ap, fmt);
 31     err_doit(1, errno, fmt, ap);
 32     va_end(ap);
 33     exit(1);
 34 }
 35 
 36 /*
 37  * Nonfatal error unrelated to a system call.
 38  * Errot code passed as explict parameter.
 39  * Print a message and return.
 40  */
 41 void
 42 err_cont(int error, const char *fmt, ...)
 43 {
 44     va_list ap;
 45 
 46     va_start(ap, fmt);
 47     err_doit(1, error, fmt, ap);
 48     va_end(ap);
 49 }
 50 
 51 /*
 52  * Fatal error unrelated to a system call.
 53  * Error code passed as explicit parameter.
 54  * Print a message and terminate.
 55  */
 56 void
 57 err_exit(int error, const char *fmt, ...)
 58 {
 59     va_list ap;
 60     
 61     va_start(ap, fmt);
 62     err_doit(1, error, fmt, ap);
 63     va_end(ap);
 64     exit(1);
 65 }
 66 
 67 /*
 68  * Fatal error related to a system call.
 69  * Print a message, dump core, and terminate.
 70  */
 71 void err_dump(const char *fmt, ...)
 72 {
 73     va_list ap;
 74 
 75     va_start(ap, fmt);
 76     err_doit(1, errno, fmt, ap);
 77     va_end(ap);
 78     abort();   /* dump core and terminate */
 79     exit(1);    /* shouldn't get here */
 80 }
 81 
 82 /*
 83  * Nonfatal error unrelated to a system call.
 84  * Print a message and return.
 85  */
 86 void
 87 err_msg(const char *fmt, ...)
 88 {
 89     va_list ap;
 90 
 91     va_start(ap, fmt);
 92     err_doit(0, 0, fmt, ap);
 93     va_end(ap);
 94 }
 95 
 96 /*
 97  * Fatal error unrelated to a system call.
 98  * Print a message and terminate.
 99  */
100 void
101 err_quit(const char *fmt, ...)
102 {
103     va_list ap;
104 
105     va_start(ap, fmt);
106     err_doit(0, 0, fmt, ap);
107     va_end(ap);
108     exit(1);
109 }
110 
111 /*
112  * Print a message and return to caller
113  * Caller specifies "errnoflag".
114  */
115 static void
116 err_doit(int errnoflag, int error, const char *fmt, va_list ap)
117 {
118     char buf[MAXLINE];
119 
120     vsnprintf(buf, MAXLINE-1, fmt, ap);
121     if (errnoflag)
122         snprintf(buf+strlen(buf), MAXLINE-strlen(buf)-1,
123         ": %s", strerror(error));
124     strcat(buf, "\n");
125     fflush(stdout);     /* in case stdout and stderr are the same */
126     fputs(buf, stderr);
127     fflush(NULL);       /* flushes all stdio output streams */
128 }

daemon_errfunc.c:

  1 /*
  2  * Error routines for programs that can run as a daemon
  3  */
  4 
  5 #include "apue.h"
  6 #include <errno.h>      /* for definition of errno */
  7 #include <stdarg.h>     /* ISO C variable arguments */
  8 #include <syslog.h>
  9 
 10 static void log_doit(int, int, int, const char *, va_list);
 11 
 12 /*
 13  * Caller must define and set this: nonzero if
 14  * interactiv, zero if daemon
 15  */
 16 extern int log_to_stderr;
 17 
 18 /*
 19  * Initialize syslog(), if running as daemon.
 20  */
 21 void
 22 log_open(const char *ident, int option, int facility)
 23 {
 24     if (log_to_stderr == 0)
 25         openlog(ident, option, facility);
 26 }
 27 
 28 /*
 29  * Nonfatal error related to a system call.
 30  * Print a message with the system's errno value and return.
 31  */
 32 void
 33 log_ret(const char *fmt, ...)
 34 {
 35     va_list ap;
 36     
 37     va_start(ap, fmt);
 38     log_doit(1, errno, LOG_ERR, fmt, ap);
 39     va_end(ap);
 40 }
 41 
 42 /*
 43  * Fatal error related to a system call.
 44  * Print a message and terminate.
 45  */
 46 void
 47 log_sys(const char *fmt, ...)
 48 {
 49     va_list ap;
 50 
 51     va_start(ap, fmt);
 52     log_doit(1, errno, LOG_ERR, fmt, ap);
 53     va_end(ap);
 54     exit(2);
 55 }
 56 
 57 /*
 58  * Nonfatal error unrelated to a system call.
 59  * Print a message and return.
 60  */
 61 void
 62 log_msg(const char *fmt, ...)
 63 {
 64     va_list ap;
 65 
 66     va_start(ap, fmt);
 67     log_doit(0, 0, LOG_ERR, fmt, ap);
 68     va_end(ap);
 69 }
 70 
 71 /*
 72  * Fatal error unrelated to a system call.
 73  * Print a message and terminate.
 74  */
 75 void
 76 log_quit(const char *fmt, ...)
 77 {
 78     va_list ap;
 79     va_start(ap, fmt);
 80     log_doit(0, 0, LOG_ERR, fmt, ap);
 81     va_end(ap);
 82     exit(2);
 83 }
 84 
 85 /*
 86  * Fatal error related to a system call.
 87  * Error number passed as an explicit parameter.
 88  * Print a message and terminate.
 89  */
 90 void
 91 log_exit(int error, const char *fmt, ...)
 92 {
 93     va_list ap;
 94 
 95     va_start(ap, fmt);
 96     log_doit(1, error, LOG_ERR, fmt, ap);
 97     va_end(ap);
 98     exit(2);
 99 }
100 
101 /*
102  * Print a message and return to caller.
103  * Caller specifies "errnoflag" and "priority".
104  */
105 static void
106 log_doit(int errnoflag, int error, int priority, 
107          const char *fmt, va_list ap)
108 {
109     char buf[MAXLINE];
110 
111     vsnprintf(buf, MAXLINE-1, fmt, ap);
112     if (errnoflag)
113         snprintf(buf+strlen(buf), MAXLINE-strlen(buf)-1,
114                  ": %s", strerror(error));
115     strcat(buf, "\n");
116     if (log_to_stderr)
117     {
118         fflush(stdout);
119         fputs(buf, stderr);
120         fflush(stderr);
121     }
122     else
123     {
124         syslog(priority, "%s", buf);
125     }
126 }

 

posted @ 2020-12-16 22:54  永恒月华  阅读(704)  评论(0编辑  收藏  举报