本文记录unix环境高级编程书里的例程问题,学习编程,最佳的捷径就是运行一遍程序,这个胜于十遍的低效阅读。
1. 资源下载
官方源码:
http://www.apuebook.com/code3e.html
2. fatal error:
apue.h
示例一是myls.c
root@ubuntu:/# cc myls.c
myls.c:1:18: fatal error: apue.h: No such file or directory
提示这个错误说明没有找到apue.h这个文件,此时找到从第一步下载的源码,解压,然后把include下的apute.h拷贝到/usr/include
目录下
cp ./apue.3e/include/apue.h /usr/include/
再次执行 gcc myls.c 提示如下错误:
myls.c:(.text+0x22): undefined reference to `err_quit'
myls.c:(.text+0x55): undefined reference to `err_sys'
这个是因为err_quit跟err_sys是作者自己定义的错误处理函数,做下面两步操作。
cp ./apue.3e/lib/error.c /usr/include/
然后
vim apue.h
在endif前添加 #include "error.c"
3. 第三章
hole.c
该例程演示了lseek函数会影响文件当前位置指针的值。
#include "apue.h"
#include <fcntl.h>
char buf1[] = "abcdefghij";
char buf2[] = "ABCDEFGHIJ";
int
main(void)
{
int fd;
if ((fd = creat("file.hole", FILE_MODE)) < 0)
err_sys("creat error");
if (write(fd, buf1, 10) != 10)
err_sys("buf1 write error");
/* offset now = 10 */
if (lseek(fd, 1024, SEEK_SET) == -1)
err_sys("lseek error");
/* offset now = 16384 */
if (write(fd, buf2, 10) != 10)
err_sys("buf2 write error");
/* offset now = 16394 */
exit(0);
}
argc[], arcv[]
argc 是 argument count的缩写,表示传入main函数的参数个数;
argv 是 argument vector的缩写,表示传入main函数的参数序列或指针,并且第一个参数argv[0]一定是程序的名称,并且包含了程序所在的完整路径,所以确切的说需要我们输入的main函数的参数个数应该是argc-1个;
下列示例为filetype.c
函数从shell命令行去读参数,每一个空格认为是一个参数,参数的个数赋值给argc,每个参数的首地址赋值给argv。
#include "apue.h"
int
main(int argc, char *argv[])
{
int i;
struct stat buf;
char *ptr;
for (i = 1; i < argc; i++) {
printf("%s: ", argv[i]);
if (lstat(argv[i], &buf) < 0) {
err_ret("lstat error");
continue;
}
if (S_ISREG(buf.st_mode))
ptr = "regular";
else if (S_ISDIR(buf.st_mode))
ptr = "directory";
else if (S_ISCHR(buf.st_mode))
ptr = "character special";
else if (S_ISBLK(buf.st_mode))
ptr = "block special";
else if (S_ISFIFO(buf.st_mode))
ptr = "fifo";
else if (S_ISLNK(buf.st_mode))
ptr = "symbolic link";
else if (S_ISSOCK(buf.st_mode))
ptr = "socket";
else
ptr = "** unknown mode **";
printf("%s\n", ptr);
}
exit(0);
}
运行结果
4. 第四章
umask.c
路径 apue.3e/filedir
设置文件权限,函数中定义了一个宏变量,引用相应的变量代表关闭该功能。
S_IRUSR: 用户读权限
S_IWUSR: 用户写权限
S_IRGRP: Group读
S_IWGRP: Group写
S_IROTH: 其它用户读
S_IWOTH: 其它用户写
相应的宏定义在这stat
结构体里,文件权限对应的 st_mode变量,这个变量也是结构体类型。
st_mode有如下几个取值
我们知道,在chmod这个命令下,输入数字即可改变文件权限,对应的数字值如下:
ebook附带的umask.c:
#include "apue.h"
#include <fcntl.h>
#define RWRWRW (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
int
main(void)
{
umask(0);
if (creat("foo", RWRWRW) < 0)
err_sys("creat error for foo");
umask(S_IRGRP|S_IWGRP | S_IROTH | S_IWOTH);
if (creat("bar", RWRWRW) < 0)
err_sys("creat error for bar");
exit(0);
}
mgm@ubuntu:~/usr/apue.3e/filedir$ gcc umask.c -o umask
mgm@ubuntu:~/usr/apue.3e/filedir$ umask //这里的umask是系统函数
0002
mgm@ubuntu:~/usr/apue.3e/filedir$ ./umask
mgm@ubuntu:~/usr/apue.3e/filedir$ ls -l foo bar
-rw------- 1 mgm mgm 0 Sep 18 02:24 bar
-rw-rw-rw- 1 mgm mgm 0 Sep 18 02:24 foo
假如我们把程序里的umask值修改一下,
#include "apue.h"
#include <fcntl.h>
#define RWRWRW (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
int
main(void)
{
umask(0);
if (creat("foo", RWRWRW) < 0)
err_sys("creat error for foo");
umask(S_IWGRP | S_IROTH | S_IWOTH);
if (creat("bar", RWRWRW) < 0)
err_sys("creat error for bar");
exit(0);
}
编译前记得把上次编译好的foo和bar函数删除。
再次执行可以看到变化。group权限多了一个读。
mgm@ubuntu:~/usr/apue.3e/filedir$ rm bar
mgm@ubuntu:~/usr/apue.3e/filedir$ rm foo
mgm@ubuntu:~/usr/apue.3e/filedir$ ./umask2
mgm@ubuntu:~/usr/apue.3e/filedir$ ls -l foo bar
-rw-r----- 1 mgm mgm 0 Sep 18 02:26 bar
-rw-rw-rw- 1 mgm mgm 0 Sep 18 02:26 foo
changemod.c
首先调用stat函数,获取结构体里的值,保存在statbuf里面。
然后用chmod函数修改st_mode的值。
#include "apue.h"
int
main(void)
{
struct stat statbuf;
/* turn on set-group-ID and turn off group-execute */
if (stat("foo", &statbuf) < 0)
err_sys("stat error for foo");
if (chmod("foo", (statbuf.st_mode & ~S_IXGRP) | S_ISGID) < 0)
err_sys("chmod error for foo");
/* set absolute mode to "rw-r--r--" */
if (chmod("bar", S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) < 0)
err_sys("chmod error for bar");
exit(0);
}