• apue2e unp安装


    最近在读 Richard Stevens 的大作《UNIX环境高级编程》,相信很多初读此书的人都会与我一样遇到这个问题,编译书中的程序实例时会出现问题,提示 “错误:apue.h:没有那个文件或目录”。

    apue.h 是作者自定义的一个头文件,并不是Unix/Linux系统自带的,此头文件包括了Unix程序所需的常用头文件及作者Richard自己写的出错处理函数。所以在默认情况下,gcc在编译时是读不到这个头文件的。

    先在这个网站 http://www.apuebook.com/src.tar.gz 下载tar.gz格式的源码包,然后解压至某个目录,比如说/home/godsoul/下,然后进入目录apue.2e。

    把文件 Make.defines.linux 中的 WKDIR=/home/xxx/apue.2e 修改为 WKDIR=/home/godsoul/apue.2e

    然后再进入apue.2e目录下的std目录,打开linux.mk,将里面的nawk全部替换为awk,如果是用的vi/vim编辑器,可以使用这个 命令  :1.$s/nawk/awk/g (注意前面有冒号)

    3 回到apue.2e目录,然后在此目录下运行make命令,即回到 /home/godsoul/apue.2e 目录在终端中输入 “./make” (不含引号)

    可能遇到的问题如下:

    如果出现stropts.h找不到的情况,则下载glibc-2.11,http://ftp.gnu.org/gnu/glibc/glibc-2.11.tar.gz解压缩tar -zxvf glibc-2.11.tar.gz
    cp ./glibc-2.11/streams/stropts.h /usr/include
    cp ./glibc-2.11/bits/stropts.h /usr/include/bits
    cp ./glibc-2.11/sysdeps/x86_64/bits/xtitypes.h /usr/include/bits

    接着 make,又会出现

    在我的机器上编译时,提示ARG_MAX未定义,可以这么修改。
    在apue.2e/include/apue.h中添加一行:
    #define ARG_MAX 4096
    打开apue.2e/threadctl/getenv1.c和apue.2e/threadctl/getenv3.c,添加一行:
    #include “apue.h”

     

    改好了,继续make,这时能通过编译了

    然后把 /home/godsoul/apue.2e/inlcude 目录下的 apue.h 文件和位于 /home/godsoul/apue.2e/lib 目录下的 error.c 文件都复制到 /usr/include 目录下,apue.2e/lib/libapue.a 到/usr/lib/和 /usr/lib64下。注意复制这文件你需要有root权限。之所以要这样做,是因为gcc在链接头文件时会到 /usr/include 这个目录下寻找需要的头文件,若找不到则报错

    最终还要编辑一下复制过来的 apue.h 文件
    在最后一行 #endif 前面添加一行 #include “error.c”

     

    例子如下:

     使用apue.h文件和libapue.a库。

    假定/tmp下有一个文件:threadid.c,内容如下(apue线程章节的例子):
    #include <apue.h>
    #include <pthread.h>

    pthread_t ntid;

    void
    printids(const char *s)
    {
    pid_t           pid;
    pthread_t       tid;

    pid = getpid();
    tid = pthread_self();
    printf(“%s pid %u tid %u (0x%x) ”, s, (unsigned int)pid,
    (unsigned int)tid, (unsigned int)tid);
    }

    void *
    thr_fn(void *arg)
    {
    printids(“new thread: “);
    return((void *)0);
    }

    int
    main(void)
    {
    int            err;

    err = pthread_create(&ntid, NULL, thr_fn, NULL);
    if (err != 0)
    err_quit(“can’t create thread: %s ”, strerror(err));
    printids(“main thread:”);
    sleep(1);
    exit(0);
    }

    使用如下命令编译:
    cc -o threadid threadid.c -lapue -lpthread
    可以运行一下:
    dan@dan-laptop:/tmp$ ./threadid
    new thread:  pid 17490 tid 816015696 (0x30a36950)
    main thread: pid 17490 tid 823949040 (0x311c76f0)

     

    配置unp的环境如下:

    3. 编译《UNP》
    这个稍微麻烦些。

    http://www.unpbook.com/unpv13e.tar.gz

    我们首先产生一个目录,以后自己的代码就敲在这个目录里。
    mkdir /home/dan/study/unp

    仍然是下载到/home/dan/download/,解压缩,进入目录
    cd /home/dan/download/unpv13e/
    README文件中说的很详细:
    ========================================
    Execute the following from the src/ directory:

    ./configure    # try to figure out all implementationdifferences

    cd lib         # build the basiclibrary that all programs need
    make           # use “gmake”everywhere on BSD/OS systems

    cd ../libfree  # continue building the basic library
    make

    cd ../libroute # only if your system supports 4.4BSD style routing sockets
    make           # only if yoursystem supports 4.4BSD style routing sockets

    cd ../libxti   # only if your system supports XTI
    make           # only if yoursystem supports XTI

    cd ../intro    # build and test a basic client program
    make daytimetcpcli
    ========================================
    这里只编译lib下的文件,这样可以产生libunp.a,复制这个静态库到/usr/lib/和/usr/lib64/
    如果提示:
    unp.h:139: error: conflicting types for ‘socklen_t’
    /usr/include/bits/socket.h:35: error: previous declaration of ‘socklen_t’ was here
    需要注释掉当前目录中unp.h的第139行。
    复制libunp.a到系统目录:
    root@dan-laptop:/home/dan/download/unpv13e/lib# cp ../libunp.a /usr/lib
    root@dan-laptop:/home/dan/download/unpv13e/lib# cp ../libunp.a /usr/lib64/

    4.使用unp.h和libunp.a
    如果直接复制unpv13e/lib/unp.h到/usr/include,那么在别的目录编译书上代码时,很可会得到类似下面的错误:
    In file included from daytimetcpsrv1.c:1:
    /usr/include/unp.h:227: error: redefinition of ‘struct sockaddr_storage’
    In file included from daytimetcpsrv1.c:1:
    /usr/include/unp.h:249:30: error: ../lib/addrinfo.h: No such file or directory
    /usr/include/unp.h:263: error: redefinition of ‘struct timespec’
    /usr/include/unp.h:363: error: conflicting types for ‘gai_strerror’
    /usr/include/netdb.h:647: error: previous declaration of ‘gai_strerror’ washere
    /usr/include/unp.h:367: error: conflicting types for ‘getnameinfo’
    /usr/include/netdb.h:653: error: previous declaration of ‘getnameinfo’ was here
    /usr/include/unp.h:371: error: conflicting types for ‘gethostname’
    /usr/include/unistd.h:857: error: previous declaration of ‘gethostname’ washere
    /usr/include/unp.h:387: error: conflicting types for ‘inet_ntop’
    /usr/include/arpa/inet.h:65: error: previous declaration of ‘inet_ntop’ washere
    /usr/include/unp.h:395: error: conflicting types for ‘pselect’
    /usr/include/sys/select.h:121: error: previous declaration of ‘pselect’ washere
    daytimetcpsrv1.c: In function ‘main’:
    daytimetcpsrv1.c:9: error: ‘MAX_LINE’ undeclared (first use in this function)
    daytimetcpsrv1.c:9: error: (Each undeclared identifier is reported only once
    daytimetcpsrv1.c:9: error: for each function it appears in.)
    dan@dan-laptop:~/study/unp/4$ rm -f /usr/include/unp.h
    解决方法有点傻:
    进入我们开始时建立的目录:
    cd /home/dan/study/unp
    复制config.h和unp.h到此目录:
    dan@dan-laptop:~/study/unp$ cp /home/dan/download/unpv13e/config.h .
    dan@dan-laptop:~/study/unp$ cp /home/dan/download/unpv13e/lib/unp.h .
    修改unp.h,
    #include “../config.h”改成 #include “config.h”
    添加一行:
    #define MAX_LINE 2048
    练习书上代码时,在unp目录下建立相应的章节目录,文件中添加一行:
    #include “../unp.h”
    编译时链接unp库就可以了。

    以第四章的daytimetcpsrv1.c为例:
    dan@dan-laptop:~/study/unp/4$ pwd
    /home/dan/study/unp/4
    dan@dan-laptop:~/study/unp/4$ cat daytimetcpsrv1.c
    #include “../unp.h”
    #include <time.h>

    int main(int argc, char **argv)
    {
    int    listenfd, connfd;
    socklen_t    len;
    struct sockaddr_in    servaddr, cliaddr;
    char    buff[MAX_LINE];
    time_t    ticks;

    listenfd = Socket(AF_INET, SOCK_STREAM, 0);

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(13);

    Bind(listenfd, (SA *)&servaddr, sizeof(servaddr));

    Listen(listenfd, LISTENQ);

    for (;;) {
    len = sizeof(cliaddr);
    connfd = Accept(listenfd, (SA *)&cliaddr, &len);
    printf(“connection from %s, port %d ”,
    Inet_ntop(AF_INET, &cliaddr.sin_addr, buff, sizeof(buff)),
    ntohs(cliaddr.sin_port));

    ticks = time(NULL);
    snprintf(buff, sizeof(buff), “%.24s ”, ctime(&ticks));
    Write(connfd, buff, strlen(buff));

    Close(connfd);
    }
    }
    编译:
    cc -o daytimetcpsrv1 daytimetcpsrv1.c -lunp
    运行一下:
    root@dan-laptop:/home/dan/study/unp/4# ./daytimetcpsrv1 &
    [1] 22106
    root@dan-laptop:/home/dan/study/unp/4#
    root@dan-laptop:/home/dan/study/unp/4# ./daytimetcpcli
    usage: a.out <IPaddress>
    root@dan-laptop:/home/dan/study/unp/4# ./daytimetcpcli 127.0.0.1
    connection from 127.0.0.1, port 42064
    Fri Aug 21 23:03:56 2009
    root@dan-laptop:/home/dan/study/unp/4# netstat -nt
    Active Internet connections (w/o servers)
    Proto Recv-Q Send-Q LocalAddress           ForeignAddress         State
    tcp        0      0127.0.0.1:13           127.0.0.1:42064         TIME_WAIT

     

  • 相关阅读:
    50 个加速包都抢不到车票,还不如这个 Python 抢票神器!
    前后端开源的一款简单的微信个人博客小程序
    可以提升3倍开发效率的 Intellij IDEA快捷键大全汇总(2019)
    一张图搞定OAuth2.0
    nginx+vue实现项目动静分离
    「今日 GitHub 趋势」让全世界程序员体会中国的 12306 抢票狂潮
    C# 获取当前月第一天和最后一天
    connect to tomcat with JMX
    Java Debugging
    内存模型
  • 原文地址:https://www.cnblogs.com/wuchanming/p/3785854.html
Copyright © 2020-2023  润新知