于帮助我们了解不同系统调用所对应的头文件,对于学习来说,这应该是一件好事。
/****************************************************************************************************************
* 其他1
******************************************************************************************************************/
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 (注意前面有冒号)
然后在此目录下运行make命令,即回到 /home/godsoul/apue.2e 目录在终端中输入 “./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.2e/std 目录,编辑linux.mk。修改里面所有的nawk为awk。
这样就不会报错了。
还又可能遇到的问题如下:
如果出现stropts.h找不到的情况,则下载glibc-2.11,解压缩
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
在我的机器上编译时,提示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 clean再重新make
2. 使用apue.h文件和libapue.a库。
假定/tmp下有一个文件:threadid.c,内容如下(apue线程章节的例子):
#include
#include
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)\n”, 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\n”, 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)
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 implementation differences
cd lib # build the basic library 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 your system supports 4.4BSD style routing sockets
cd ../libxti # only if your system supports XTI
make # only if your system 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’ was here
/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’ was here
/usr/include/unp.h:387: error: conflicting types for ‘inet_ntop’
/usr/include/arpa/inet.h:65: error: previous declaration of ‘inet_ntop’ was here
/usr/include/unp.h:395: error: conflicting types for ‘pselect’
/usr/include/sys/select.h:121: error: previous declaration of ‘pselect’ was here
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/4rm−f/usr/include/unp.h解决方法有点傻:进入我们开始时建立的目录:cd/home/dan/study/unp复制config.h和unp.h到此目录:dan@dan−laptop: /study/unpcp /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/4pwd/home/dan/study/unp/4dan@dan−laptop: /study/unp/4 cat daytimetcpsrv1.c
#include “../unp.h”
#include
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\n”,
Inet_ntop(AF_INET, &cliaddr.sin_addr, buff, sizeof(buff)),
ntohs(cliaddr.sin_port));
ticks = time(NULL);
snprintf(buff, sizeof(buff), “%.24s\r\n”, 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
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 Local Address Foreign Address State
tcp 0 0 127.0.0.1:13 127.0.0.1:42064 TIME_WAIT
/*****************************************************************************************************
* 其他2
*****************************************************************************************************/
提示 "错误:apue.h:没有那个文件或目录".
很是受打击,果断google解决之。
apue.h是作者自定义的一个头文件,包括程序所需的常用头文件及出错处理函数。所以因该将它放入系统头文件中(Linux下是 /usr/include),这样gcc编译器就可以找到它了。
去http://www.linuxidc.com/Linux/2013-01/77467.htm下载src.tar.gz包,然后解压至电脑中的某个目录,比如我的是在/home/user/下
user@user-desktop:~$ sudo tar xzf src.tar.gz
进入解压目录apue.2e,修改 Make.defines.linux中的WKDIR=/home/xxx/apue.2e,为WKDIR=/home/user/apue.2e
进入std目录,修改linux.mk,将里面的nawk全部改为awk。
复制apue.h和error.c
将apue.h和error.c两个文件copy到/usr/include目录下。(apue.h位于 your_apue_path/inlcude ; error.c位于your_apue_path/lib )
以我的路径为例:
user@user-desktop:/usr/include$ cp /home/user/apue.2e/inlcude/apue.h apue.h
user@user-desktop:/usr/include$ cp /home/user/apue.2e/lib/error.c error.c (实现apue.h中的出错处理函数)
修改apue.h
在最后一行#endif 前面添加一行 #include "error.c"
貌似这样就OK了。
UNIX环境高级编程中文第二版PDF高清版 http://www.linuxidc.net/thread-2063-1-1.html
/******************************************************************
****** Ubuntu系统的移植编译
*******************************************************************
按照上面的诸多方法变异会出现下面两个错误:
make[2]: *** [printd.o] 错误 1
错误的原因:
1. 在apue.2e/ipp.h中定义了一个宏定义status和/usr/include/i386-linux-gnu/bits/timex.h中的成员status冲突
2. ARG_MAX未定义
解决办法:
1. 修改这个apue.2e/ipp/ipp.h文件中的宏名称,例如改为Status;然后将apue.2e/ipp/printd.c中977行的 hp->status 改为hp->Status;
2. 在apue.2e/include/apue.h中添加一行: #define ARG_MAX 4096
3. 在路径下的文件apue.2e/threadctl/getenv1.c 和apue.2e/threadctl/getenv3.c,添加一行:#include "apue.h"
/* 编辑成库文件以供其他程序使用 */
1、修改相应平台的文件,将Make.defines.linux文件中的 WKDIR=/home/your_dir/apue.2e, 其中/home/your_dir为Apue.2e包的路径;
2. 使用make命令在上述路径下编译通过;
3. 把apue的头文件和库文件放入系统,具体如下:使用sudo su使用root权限,复制文件到系统默认搜索路径下
cp ~/apue.2e/include/apue.h /usr/include
cp ~/apue.2e/lib/libapue.a /usr/lib/
其中~为/home/your_dir
4. 这样库文件就编译和设置好了,使用APUE书中带#include "apue.h"的程序,只需引用此库即可
gcc source.c -o excutename -lapue
如:gcc Hello.c -0 Hello -lapue Hello.c 为要编译的程序名,Hello为可执行文件名