缘由
花了接近一周的时间死劲的读新买了的:unix高级环境编程
所以,没有写博客,现在差不多大概读完了,但是没有敲代码,没有查看练习题,只是对这本书有一个粗浅的认识。
现在的计划是:
- 敲完书中所有的例子代码
- 然后解决练习题
注意:主要是写代码,不会重复书中的话。当然真的有价值的总结还是会进行的,原来犯的错误就是老是总结书中的观点、重复书中的话,非常耽误时间。
- 今天是unix的基础知识,所以还看不出这些代码的价值,越到后面就越能看出书中代码的宝贵
配置头文件
书中大量使用apue.h和打印错误的error.c,首先要把就两个头文件加入编写的代码里面。
需要的代码可以从这里下载:源代码
搭配的问题可参考:看unix高级编程时遇到apue.h找不到的问题
程序清单1-1:列出一个目录中的所有文件
#include "apue.h"
#include <dirent.h>
#include "error.c" /*不是.h*/
/**
* 程序清单1-1:列出一个目录中的所有文件(P4)
*
* zy:
* 现实了简单的ls的功能,请添加头文件
* 第五页对此有详细的解释,由于非常简单,就不多解释了
*/
int main(int argc,char *argv[]){
DIR *dp;
struct dirent *dirp;
if(argc!=2){
err_quit("usage: ls directory_name");
}
if ((dp=opendir(argv[1]))== NULL){
err_sys("can't open %s",argv[1]);
}
while((dirp=readdir(dp))!=NULL){
printf("%s\n",dirp->d_name);
}
closedir(dp);
exit(0);
}
程序清单1-2:将标准输入复制到标准输出
/**
* 程序清单1-2:将标准输入复制到标准输出(P6)
*
* zy:
* 对标准输入和标准输出有加深认识.
* 试用了P7所说的几种方法
* 改变标准输入和标准输出。
*/
#include "apue.h"
#include "error.c" /*不是.h*/
#define BUFFSIZE 4096
int main(){
int n;
char buf[BUFFSIZE];
while((n = read(STDIN_FILENO,buf,BUFFSIZE))>0){
if(write(STDOUT_FILENO,buf,n)!=n){
err_sys("write error");
}
}
if(n<0)
err_sys("read error");
}
程序清单1-3:用标准I/O将标准输入复制到标准输出
/**
* 程序清单1-3:用标准I/O将标准输入复制到标准输出
*
* zy:
* 和上一个程序的区别主要在于使用了getc,而不是read
* 使用了putc,而不是write.
* 从P7的描述来看,read和write应该是系统调用,需要我们自己关心缓冲区问题
* I/O标准库的函数为我们提供了一系列的函数,让我们不用担心缓冲区的问题,
* 比如fgets读一行,getc和putc是一个字节
*
* */
#include "apue.h"
#include "error.c" /*不是.h*/
int main()
{
int c;
while((c=getc(stdin))!=EOF)
if(putc(c,stdout)==EOF)
err_sys("output,error");
if(ferror(stdin))
err_sys("input error");
exit(0);
}
程序清单1-4:打印进程ID
/**
* 程序清单1-4:打印进程ID
*
* zy:
* 本来很简单的问题,但是请记住,
* 这个getpid()的来自库文件:unistd.h
* */
#include "apue.h"
#include "error.c" /*不是.h*/
int main()
{
printf("the pid:%d\n",getpid());
}
程序清单1-5:从标准输入读命令并且执行
/**
* 程序清单1-5:从标准输入读命令并且执行
*
* zy:
* 相当于完成了一个小shell
* 因为子进程执行了execlp
* */
#include "apue.h"
#include "sys/wait.h" /*不是.h*/
#include "error.c"
int main()
{
char buf[MAXLINE];
pid_t pid;
int status;
printf("%% ");//打印一个提示符
while(fgets(buf,MAXLINE,stdin)!=NULL){
if(buf[strlen(buf)-1]=='\n')
buf[strlen(buf)-1]=0;//用null代替换行符(我居然写成了‘0’),这是下面那个execlp的要求
if((pid=fork())<0){
err_sys("fork error");
}else if(pid==0){//child
execlp(buf,buf,(char *)0);
err_ret("couldn't execute :%s ",buf);
exit(127);
}
//parent
if((pid=waitpid(pid,&status,0))<0)//P179对此函数有着更多的说明
err_sys("waitpid error");
printf("%% ");
}
}
程序清单1-6:例示strerror和perror
/**
* 程序清单1-6:例示strerror和perror
*
* zy:
* strerror只是产生一个字符串,然后我们还要手动将其打印出来,
* 而perror要方便多了,对errno赋值之后,我们可以直接调用perror
* */
#include "apue.h"
#include "error.c"
int main(int argc,char *argv[])
{
fprintf(stderr,"EACCES:%s\n",strerror(EACCES));
errno=ENOENT;//这个errno是c标准里面定义好的东西
perror(argv[0]);
}
结果:
zy@zy:~/Documents/eclipseWorkSpace/test/src$ ./a.out
EACCES:Permission denied
./a.out: No such file or directory
zy@zy:~/Documents/eclipseWorkSpace/test/src$
程序清单1-7:打印用户ID和组ID
/**
* 程序清单1-7:打印用户ID和组ID
*
* */
#include "apue.h"
#include "error.c" /*不是.h*/
int main()
{
printf("the uid:%d,gid=%d\n",getuid(),getgid());
exit(0);
}
程序清单1-8:从标准输入读命令并执行,涉及信号
/**
* 程序清单1-8:从标准输入读命令并执行,涉及信号
*
* zy:
* 主要是简单的认识一下信号,这里的SIGINT信号没有采用默认的方法,而是被截断了执行sig_int的方法
* */
#include "apue.h"
#include "sys/wait.h" /*不是.h*/
#include "error.c"
void sig_int(int signo){
printf("interrupt\%%");
}
int main()
{
char buf[MAXLINE];
pid_t pid;
int status;
if(signal(SIGINT,sig_int)==SIG_ERR)
err_sys("signal error");
printf("%% ");//打印一个提示符
while(fgets(buf,MAXLINE,stdin)!=NULL){
if(buf[strlen(buf)-1]=='\n')
buf[strlen(buf)-1]=0;//用null代替换行符(我居然写成了‘0’),这是下面那个execlp的要求
if((pid=fork())<0){
err_sys("fork error");
}else if(pid==0){//child
execlp(buf,buf,(char *)0);
err_ret("couldn't execute :%s ",buf);
exit(127);
}
//parent
if((pid=waitpid(pid,&status,0))<0)//P179对此函数有着更多的说明
err_sys("waitpid error");
printf("%% ");
}
}
其它问题总结
eclipse下C/C++自动补全
关键就是如下图中的那个Content Assist: