Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1757267
  • 博文数量: 293
  • 博客积分: 10574
  • 博客等级: 上将
  • 技术积分: 5085
  • 用 户 组: 普通用户
  • 注册时间: 2006-12-22 17:00
文章分类

全部博文(293)

文章存档

2011年(27)

2010年(84)

2009年(62)

2008年(120)

我的朋友

分类: C/C++

2010-01-28 20:11:44

第3章 文件I/O

* ssize_t read(int fd, void *buf, size_t count); 函数在从文件描述符中读时,很多原因导致读不到count个字符,所以在进行读取操作时需要处理一下,特别是在进行网络和管道读取的时候。

    一般的处理方式是 while((rt = read(fd, buffer, size) == -1)  && (errno == EINTR) );

    另外,在网络编程中需要特殊处理。

*原子操作的概念。

*用open函数创建新文件,定位文件的写位置;当文件存在时的处理方式。

文件不存在就创建,文件存在就截断成0,

    open(filename,  O_WRONLY | O_CREAT | O_TRUNC,  S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)

文件不存在就创建: 

    open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0666)

*dup 和 dup2 的使用,下面是一个例子:

view plaincopy to clipboardprint?
if ((fd = open("temp", O_RDWR | O_APPEND | O_CREAT | O_TRUNC, 0766)) < 0) {  
    perror("open(): ");  
    exit(1);  
}     
//save 2  
fd1 = dup(2);     
dup2(fd, 0);      
dup2(fd, 1);   
dup2(fd, 2);   
write(fd, "123\n", 4);   
printf("456\n");  
fprintf(stderr, "8910\n");  
//restore 2  
dup2(fd1, 2);   
fprintf(stderr, "11 12 13 14 15\n");  
return 0;    
    if ((fd = open("temp", O_RDWR | O_APPEND | O_CREAT | O_TRUNC, 0766)) < 0) {
        perror("open(): ");
        exit(1);
    }  
    //save 2
    fd1 = dup(2);  
    dup2(fd, 0);   
    dup2(fd, 1);
    dup2(fd, 2);
    write(fd, "123\n", 4);
    printf("456\n");
    fprintf(stderr, "8910\n");
    //restore 2
    dup2(fd1, 2);
    fprintf(stderr, "11 12 13 14 15\n");
    return 0;  


为了恢复重定向的描述符,需要先用dup进行保存,再用dup2来恢复,如上面的代码。

*缓冲区高速缓存函数sync,fsync,fdatasync的功能和区别

    磁盘i/o的缓冲机制: 数据->缓冲区->缓冲区满或内核需要使用该缓冲区->输出队列->到达队列首->进行i/o操作

sync :  将所有修改的缓冲区排入写队列

fsync:  等待写磁盘操作结束,会改变文件的属性

fdatasync:  和fsync类似,但只针对数据,不改变文件属性

*fcntl函数的用法 ????

*ioctl函数的用法????

第4章 文件和目录

 


*state,fstate,lstat这几个函数的区别和用法
*如何判断一个文件的类型

    + expand sourceview plaincopy to clipboardprint?
int 
main(int argc, char *argv[])  
{  
    struct stat buf;  
    if (argc != 2) {  
        fprintf(stderr, "Usage : %s filename\n", argv[0]);  
        exit(1);  
    }     
    if (lstat(argv[1], &buf) < 0) {  
        perror("lstat : %s\n");  
        return -1;   
    }  
    if (S_ISREG(buf.st_mode))      
        printf("regular file\n");  
              
    return 0;  
}  
~            
int
main(int argc, char *argv[])
{
    struct stat buf;
    if (argc != 2) {
        fprintf(stderr, "Usage : %s filename\n", argv[0]);
        exit(1);
    }  
    if (lstat(argv[1], &buf) < 0) {
        perror("lstat : %s\n");
        return -1;
    }
    if (S_ISREG(buf.st_mode))   
        printf("regular file\n");
           
    return 0;
}
~          

上面的代码只能判断 regular类型的文件,若想判断其他的文件类型,请查询手册 man lstate 的st_mode节

*进程相关联的几个ID: 实际用户ID,有效用户ID,设置用户ID

实际用户ID: 来自/etc/passwd 的用户名和组名

有效用户ID: 访问文件时的用户ID或组ID

设置用户ID: 保存了实际用户ID,如果设置了S属性,就把有效用户ID设置成文件的所有者,如程序 passwd

    对设置用户ID进行测试可以用: stat 函数的 S_ISUID 和 S_ISGID来进行测试是否设置了该字段

*文件的访问权限???

*新文件和目录的所有权是如何设置的?

文件和目录的权限设置基本上一样。

view plaincopy to clipboardprint?
[zhengxh@jsdlinux temp]$ chmod a+s test  
[zhengxh@jsdlinux temp]$ ls  
[zhengxh@jsdlinux test]$ sudo su   
[root@jsdlinux test]# ls  
[root@jsdlinux test]# cat > tt  
adfadf  
[root@jsdlinux test]# ls -l  
总计 4  
-rw-r--r-- 1 root zhengxh 7 02-06 16:11 tt  
[root@jsdlinux test]# cd .. 
[zhengxh@jsdlinux temp]$ chmod a+s test
[zhengxh@jsdlinux temp]$ ls
[zhengxh@jsdlinux test]$ sudo su
[root@jsdlinux test]# ls
[root@jsdlinux test]# cat > tt
adfadf
[root@jsdlinux test]# ls -l
总计 4
-rw-r--r-- 1 root zhengxh 7 02-06 16:11 tt
[root@jsdlinux test]# cd ..
 

(1)新文件的用户ID设置成进程的有效用户ID

(2)新文件的组ID的设置分成两种情况:如果所在目录设置了设置用户ID,则该新文件的组ID设置成所在目录的设置用户ID

    否则,设置成进程的组用户ID

如上面代码所示。

*文件屏蔽字的设置--umask函数

    1,每个系统都有一个默认的umask值,当建立新文件时,将按照这个值来进行权限的设定: 0777-umask(0022)

    2,如果不确定系统的默认权限,需要使用umask对权限进行设定。

    3,目录的默认权限中有x位,但新文件却没有x位

    4,具体使用请参考: man umask

*改变文件的访问权限

    只有文件的所有者,和超级用户才能改变文件的权限。

    (1) 在原有的基础上更改:

            stat(filename, &statbuf)

            chmod(filename, (statbuf.st_mode & S_IXGRP) | S_ISGID)

    (2) 设置成固定的值

             chmod(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)

*

第7章 进程环境

*main函数是如何开始执行的?
    内核exec一个启动例程(准备好main的参数和环境变量等) ----> main()--->其他函数

*进程终止的方式?

    从main返回;exit;_exit或_Exit;调用abort;接到一个信号并终止。

*线程终止的方式?
    最后一个线程从启动例程返回;最后一个线程调用pthread_exit;最后一个线程对取消请求做出响应。

*exit和_exit的区别?
    exit 函数总是执行一个标准I/O库的清理关闭操作(fclose),调用执行各种终止处理程序(由atexit注册的函数)。

*什么是进程的返回状态?

    每个进程都会返回一个整数值给shell,来表示他的状态是正常返回还是错误返回。

    在main函数中调用:exit(int) 或 return(int)就向shell返回这个状态。

    如果这样调用返回状态是未知的: return; 或这样申明main函数: void/char main; 或根本不调用return或exit;

*进程的环境表是什么?如何操作环境表?

    进程的环境表是一个字符指针数组,其中每个字符串以null结尾。

    全局变量environ指向这个字符串数组的首地址,通过它可以访问整个环境表。

    getenv和putenv函数可以对某个环境表的项进行操作。

*进程的存储空间布局是怎样的?
.低地址--------------------------------------------------------------------------->高地址
.正文段-->初始化数据(数据段)-->未初始化的数据(bss段,由exec初始化为0)-->堆-->栈-->环境变量,参数
.说明:正文段和初始化段数据是由内核从程序文件中读入。其他的段都不从程序文件中读入。
.size命令可以查看一个可以执行文件的各段的长度。

*共享库的概念?如何制作共享库?????
        
*如何动态分配内存,各个函数调用的区别?
malloc 分配指定字节数的内存,不初始化。
calloc 分配指定对象,和指定数量的内存,每位都初始化为0。
realloc 在原来的基础上增加内存,不初始化。
free  释放由上面的三个函数分配的内存。
alloca 在栈段上分配内存,自动释放分配的空间。但有的系统不能增加栈空间,该函数将失败。

*如何修改环境变量?如何添加环境变量?
可以用以下函数实现这些功能:
    putenv; setenv; unsetenv

*setjmp和longjmp的用法?

请看例子:

+ expand sourceview plaincopy to clipboardprint?
#include   
#include   
#include   
#include   
void do_line(char *ptr);  
void f2(void);  
#define MAXLINE 128  
jmp_buf jbuf;           //定义全局跳转变量  
int 
main(void)  
{  
    char line[MAXLINE];   
    int jd;   
    /*   
     * 若setjmp直接返回正确,返回值为0;如:第一次设定正确时  
     * 若用于longjmp的调用而返回, 
     * 返回值为longjmp的第2个参数的数值。 
     */      
    if ((jd = setjmp(jbuf)) != 0)  
        fprintf(stderr, "setjmp = %d\n", jd);  
    if (fgets(line, MAXLINE, stdin) != NULL)  
        do_line(line);  
      
    fprintf(stderr, "Now I go away!\n");  
    exit(0);  
}  
void 
do_line(char *ptr)  
{  
    if (strstr(ptr, "exit") != NULL)  
        return;  
    if (strstr(ptr, "zhengxh") != NULL)  
        f2();  
    else 
        longjmp(jbuf, 20);  //跳转到设置(setjmp)jbuf变量的地方,使得setjmp返回值为20  
}  
void 
f2(void)  
{  
   //跳转到设置jbuf的地方,使得setjmp返回值为1  
    longjmp(jbuf, 1);    
}  
~                                 
#include
#include
#include
#include
void do_line(char *ptr);
void f2(void);
#define MAXLINE 128
jmp_buf jbuf;           //定义全局跳转变量
int
main(void)
{
    char line[MAXLINE];
    int jd;
    /* 
     * 若setjmp直接返回正确,返回值为0;如:第一次设定正确时
     * 若用于longjmp的调用而返回,
     * 返回值为longjmp的第2个参数的数值。
     */   
    if ((jd = setjmp(jbuf)) != 0)
        fprintf(stderr, "setjmp = %d\n", jd);
    if (fgets(line, MAXLINE, stdin) != NULL)
        do_line(line);
   
    fprintf(stderr, "Now I go away!\n");
    exit(0);
}
void
do_line(char *ptr)
{
    if (strstr(ptr, "exit") != NULL)
        return;
    if (strstr(ptr, "zhengxh") != NULL)
        f2();
    else
        longjmp(jbuf, 20);  //跳转到设置(setjmp)jbuf变量的地方,使得setjmp返回值为20
}
void
f2(void)
{
   //跳转到设置jbuf的地方,使得setjmp返回值为1
    longjmp(jbuf, 1); 
}
~                               

注意: 在使用这两个函数进行跳转时,在函数中的自动变量的值的改变将会丢失,
    而volatile 定义的变量,全局变量,静态变量则不会。所以在编程时要注意。

*如何对每个进程的资源进行限制?

    .用getrlimit 和 setrlimit可以做到,具体查看手册:man getrlimit

第8章 进程控制

*进程控制包括:创建新进程,执行进程,终止进程。

*基础知识

*进程标识
每个进程由一个正整数唯一标识,若该进程终止,它的进程标识整数可以被其他进程使用。
L/Unix系统中 0进程表示swapper进程,它不执行磁盘上的代码,所以被称为系统进程。
1 负责在自举后启动一个UNIX系统,通常配合/etc/rc*等文件启动系统。

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/zg_hover/archive/2009/02/06/3866041.aspx

阅读(1625) | 评论(0) | 转发(0) |
0

上一篇:浅谈C中的malloc 和 free

下一篇:没有了

给主人留下些什么吧!~~