学习APUE笔记3-文件系统

三、文件系统:

1、目录和文件

2、系统数据文件和信息

3、进程环境

 

类ls的实现,如myls

/etc/group

/etc/passwd

 

一、目录和文件

1、获取文件属性

stat: 通过文件路径获取属性,面对符号链接文件时获取的是所指向的目标文件的属性。

fstat:通过文件描述符获取属性。

lstat:面对符号链接文件时获取符号链接文件的属性。

 

查看文件的属性:将参数path所指的文件状态复制到参数buf所指的结构中

int stat(const char *path, struct stat *buf);

int fstat(int fd, struct stat *buf);

int lstat(const char *path, struct stat *buf);

返回值:成功,返回0; 失败, 返回-1,设置errno.

 

#include <stdio.h>

#include <stdlib.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <unistd.h>

 

off_t flen(const char *path)

{

struct stat  statres;

 

if(stat(path,&statres) < 0)

{

perror("stat()");

exit(1);

}

 

return statres.st_size;

}

 

int main(int argc ,char **argv)

{

 

if(argc < 2)

{

fprintf(stderr,"Usage....\n");

exit(1);

}

 

printf("%lld\n",flen(argv[1]));

 

exit(0);

}

 

文件类型

普通文件     -

目录文件     d

字符设备文件 c

块设备文件   b

符号链接     l

网络套接字   s

管道(FIFO)   p

 

2、文件访问权限

st_mode是一个16位的位图,用于表示文件类型,文件访问权限以及特殊权限位。

 

3、umask用来设定系统中新创建文件的默认权限的

文件掩码是linux系统中维护的一个全局设置

0666 & ~umask

作用:为进程设置文件权限(模式)创建掩码(屏蔽字),防止产生权限过松的文件。

 

修改进程的文件模式创建屏蔽字:mode_t umask(mode_t mask);

返回值:之前的文件模式创建屏蔽字。

修改屏蔽字为 mask&0777,返回就的屏蔽字

注意:进程的屏蔽字是继承于父进程,umask 不会改变父进程的屏蔽字

 

4、现有文件权限的更改/管理  chmod fchmod

 

把文件的权限设置为 mode

int chmod(const char *pathname, mode_t mode);

pathname参数为绝对路径

返回值:成功,返回0; 出错, 返回-1.

 

修改打开文件的访问权限

int fchmod(int fd, mode_t mode);

返回值:成功,返回0; 出错, 返回-1.

 

注意:chmod函数不受文件模式屏蔽字的约束,要想改变一个文件的权限位,进程的有效用户ID必须等于文件所有者ID或者进程的有效用户ID是0.

 

5、粘住位  t位

文件的文件模式中可以设置一个位,此位为粘住位S_ISVTX。即文件模式0777中的0。

如果在一个执行文件设置了该位,则执行该文件且进程结束后,系统会把该进程的正文部分放置磁盘的交换区中,

(在交换区中文件是连续存放的,不像非交换区一样,一个文件的内容分散在磁盘的几个块中.)

所以在加载该执行文件时就可以加快速度启动,直接从交换区中把进程的正文部分取至内存中运行。

 

6、文件系统:FAT,UFS

文件系统:文件或数据的存储和管理

FAT16/32 静态存储单链表

 

7、硬链接,符号链接 link ulink remove rename

 

区别与联系:

硬链接与目录是同义词,且建立硬链接有限制;不能给分区建立,不能给目录建立。

符号链接优点:可跨分区, 可以给目录建立。

 

硬链接:ln  bigfile bigfile_link (给一个文件做了一个硬链接)

硬链接其实就是指向 i 节点的一个目录项,如果有多个目录项指向同一个i节点,

那么该i节点表示的文件就有多个链接,删除一个文件其实就是删除了一个目录项,

也就是解除了一个链接,当一个文件的链接数为 0 的时候,这个文件的实际内容才会被删除。

 

符号链接:符号链接是一个独立的文件,这个文件的内容是指向的文件的路径名。

ln -s bigfile_link bigfile_s

 

创建一个现有文件的链接: int link(const char *oldpath, const char *newpath);

返回值:成功,返回0; 出错, 返回-1.

参数oldpath表示现有文件,参数newpath表示新目录项。

 

解除一个已有文件的链接: int unlink(const char *pathname);

返回值:成功,返回0; 出错, 返回-1.

删除目录项,并将pathname所引用文件的链接计数减1.

 

unlink创建匿名文件

方法:open一个文件然后unlink, colse可以释放。

 

删除一个文件或目录:int remove(count char *pathname)

相当于rm

 

改变一个文件的名字或位置:int rename(count char *oldpath, count char *newpath)

返回值:成功,返回0; 出错, 返回-1.

相当于mv

 

8、utime:可以更改的最后一次读的时间和写的时间

 

9、目录的创建和销毁 mkdir rmdir

 

创建目录:int mkdir(const char *pathname, mode_t mode);

删除目录:int rmdir(const char *pathname);

打开目录:DIR *opendir(const char *name);   /DIR *fdopendir(int fd);

关闭目录:int closedir(DIR *dirp);

读目录:struct dirent *readdir(DIR *dirp);

写目录:void rewinddir(DIR *dirp);

 

10、更改当前工作路径  chdir  fchdir

 

1>更改工作路径

int chdir(const char *path);

int fchdir(int fd);

参数path或fd为新的当前工作目录。

返回值:成功,返回0;出错,返回-1.

 

2>获得当前工作路径

char *getcwd(char *buf, size_t size);

参数buf表示缓冲区地址,参数size表示缓冲区长度

返回值:成功,返回buf; 失败,返回NULL。

char *getwd(char *buf);

char *get_current_dir_name(void);

 

注意:如果 buf 的空间不够大,则会出错返回 NULL

注意:如果 getcwd 中的 buf 为 NULL,系统会分配 size 大小的内存,用户需要 free

注意:用户需要 free get_current 函数返回的内存

注意:工作路径是进程的属性,因此子进程调用 chdir 不会改变父进程的工作路径

 

11、分析目录/读取目录内容  

du可以分析出来一个目录或一个文件所占磁盘空间的大小,以K为单位。

如:du 文件名/目录名

 

12、glob():解析模式/通配符

glob库函数用于Linux文件系统中路径名称的模式匹配,即查找文件系统中指定模式的路径。

注意,这不是正则表达式匹配,虽然有些相似,但还是有点差别。

 

glob函数原型

       #include <glob.h>

 

       int glob(const char *pattern, int flags,

                           int errfunc(const char *epath, int eerrno),

                           glob_t *pglob);

glob函数搜索匹配 函数pattern中的参数,

如:/*是匹配根文件下的所有文件(不包括隐藏文件,要找的隐藏文件需要从新匹配),然后会将匹配出的结果存放到 pglob,即第4个参数中,

第二个参数能选择匹配模式,如:是否排序,或者在函数第二次调用时,是否将匹配的内容追加到pglob中等,第3个参数是查看错误信息用,一般置为NULL;

 

#include <stdio.h>

#include <stdlib.h>

#include <glob.h>

 

#define PAT "/etc/a*.conf"

 

int err_func(const char *epath, int eerrno)

{

printf("%s:%s\n",epath,strerror(eerrno));

}

 

int main(int argc,char *argv[])

{

int i,err;

glob_t globres;

 

err = glob(PAT,0,NULL/*err_func*/,&globres);

if(err)

{

printf("err = %d\n",err);

exit(1);

}

 

for(i = 0 ; i < globres.gl_pathc; i++)

puts(globres.gl_pathv[i]);

 

globfree(&globres);

 

exit(0);

}

 

一个变量它的使用是单纯的在递归点之前,那么在这个变量可以优化到静态区去存放,甚至可以放到全局位置也没有关系。

 

opendir();

closedir();  

readdir(3);

rewinddir();

seekdir();

telldir();

二、系统数据文件和信息

 

1、/etc/passwd(账户信息)

不同系统环境中的口令文件支持不一样。

1>读取口令文件:(查询用户信息)

struct passwd *getpwnam(const char *name);

struct passwd *getpwuid(uid_t uid);

返回值:成功:返回指针; 出错,返回NULL。

注意:这两个函数不可重入

           struct passwd {

               char   *pw_name;       /* username */

               char   *pw_passwd;     /* user password */

               uid_t   pw_uid;        /* user ID */

               gid_t   pw_gid;        /* group ID */

               char   *pw_gecos;      /* user information */

               char   *pw_dir;        /* home directory */

               char   *pw_shell;      /* shell program */

           };

 

[组信息,函数,和加密原理讲解]

2、/etc/group(组信息)

1>查询组的相关信息

struct group *getgrnam(const char *name);

struct group *getgruid(uid_t uid);

返回值:成功:返回指针; 出错,返回NULL。

           struct group {

               char   *gr_name;     /* group name */

               char   *gr_passwd;   /* group password */

               gid_t   gr_gid;      /* group ID */

               char  **gr_mem;      /* NULL-terminated array of pointers

                                          to names of group members */

           };

 

3、/etc/shadow(加密口令)

普通用户下:cat /etc/shadow(无法查看权限不够)

(root下)

阴影文件格式

用户名:密码:最近修改时间:::

zhiyong:$6$mrFIWNAI$Iy788XD2BtJn9gImM9cyZZCQPHP7.OE8RzLzyalwM1WfAcuiP20nW

4Zfrackk6Qzq10eOze5BEWAMb1NsSA371:16295:0:99999:7:::

 

6表示加密方式 mrFIWNAI表示杂字串(原串或上杂字经过加密的到Iy788XD2BtJn9gImM9cyZZCQPHP7.OE8RzLzyalwM1WfAcuiP20nW

4Zfrackk6Qzq10eOze5BEWAMb1NsSA371)

 

1>通过阴影密码文件API

struct spwd *getspnam(const char *name);

返回值:成功:返回指针; 出错,返回NULL。

 

2>密码和数据加密

char *crypt(const char *key, const char *salt);

key表示口令原文

返回值:成功:返回加密密码的指针; 出错,返回NULL。

 

hash: 混淆(不可逆) 如果原串相同,所得串也相同,需防备管理员监守自盗

加密:安全:攻击成本大于收益

安全? 穷举:口令随机校验

 

//[密码校验实例]

#include<stdio.h>

#include<stdlib.h>

#include<unistd.h>

#include<shadow.h>

#include<string.h>

int main(int argc, char **argv)

{

    char *input_pass;

    struct spwd *shadowline;

    char *crypted_pass;

    if(argc < 2)

    {

        fprintf(stderr, "Usage...\n");

        exit(1);

    }

    input_pass = getpass("Password:");//获取口令  password提示符

    shadowline = getspnam(argv[1]);//访问口令文件获取所有信息

    crypted_pass = crypt(input_pass, shadowline->sp_pwdp);//加密

    if(strcmp(shadowline->sp_pwdp,crypted_pass) == 0)

        puts("OK!");

    else

        puts("faile!");

    exit(0);

}

 

4、时间戳

[时间函数精讲]

1>得到以秒为单位的时间

time_t time(time_t *t);

返回值:返回 UTC 时间(从 1970-01-01 00:00:00 开始的秒数); 出错, 返回-1

 

2>将日历时间转换成协调统一时间的年月日十分秒周日分解结构

struct tm *gmtime(const time_t *timep);

返回值:指向分解的tm结构的指针; 出错, 返回NULL。

 

3>将日历时间转换成本地时间

struct tm *localtime(const time_t *timep);

返回值:指向分解的tm结构的指针; 出错, 返回NULL。

 

4>以本地时间的年月日等作为参数,将其变换成time_t值

time_t mktime(struct tm *tm);

返回值:成功返回日历时间,出错返回-1.

           struct tm {

               int tm_sec;    /* Seconds (0-60) */

               int tm_min;    /* Minutes (0-59) */

               int tm_hour;   /* Hours (0-23) */

               int tm_mday;   /* Day of the month (1-31) */

               int tm_mon;    /* Month (0-11) */

               int tm_year;   /* Year - 1900 */

               int tm_wday;   /* Day of the week (0-6, Sunday = 0) */

               int tm_yday;   /* Day in the year (0-365, 1 Jan = 0) */

               int tm_isdst;  /* Daylight saving time */

           };

 

5>类似于printf的时间值函数。可以通过可用的多个参数来制定产生的字符串。

size_t strftime(char *s, size_t max, const char *format,const struct tm *tm);

s表示所放内容的位置,空间大小为max,format为格式串,从tm中抽取

返回值:若有空间,返回存入数组的字符数; 否则,返回0.

 

[时间实例1]

//获取一个时间一秒钟向终端打印一次

//同时具有过一段时间依然能获取当前时间输出

#include <stdio.h>

#include <stdlib.h>

#include <time.h>

#include <unistd.h>

#define FNAME "/tmp/out"

#define BUFSIZE 1024

int main()

{

struct tm *tm;

time_t stamp;

int no;

char buf[BUFSIZE];

FILE *fp;

fp = fopen(FNAME,"a+");//打开FANME文件 用追加读写

if(fp == NULL)

{

perror("fopen()");

exit(1);

}

while(fgets(buf,BUFSIZE,fp) != NULL)//从fp读取内容到buf中,字节大小BUFSIZE

no++;

while(1)

{

time(&stamp);//获取时戳

tm = localtime(&stamp);//转换成结构体

fprintf(fp,"%-4d%d-%d-%d %d:%d:%d\n",

++no,tm->tm_year+1900,tm->tm_mon+1,

tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec);

//no自增换行

fflush(fp);

sleep(1);

}

fclose(fp);

exit(0);

}    

[]$ ./timelog

切换终端执行

[]$ tail -f /tmp/out

 

[时间函数实例2]

//一年任意一天的一百天后是什么时间

#include <stdio.h>

#include <stdlib.h>

#include <time.h>

 

#define BUFSIZE 1024

 

int main()

{

struct tm *tm;

time_t stamp;

char buf[BUFSIZE];//缓冲区

 

stamp = time(NULL);//获取时戳

tm = localtime(&stamp);//转换成结构体

strftime(buf,BUFSIZE,"Now:%Y-%m-%d",tm);

//显示当前年月日,从tm中抽取放到buf中,空间大小为BUFSIZE。

puts(buf);//标准输出

 

tm->tm_mday += 100;

mktime(tm);//可以自动将时间进位。

strftime(buf,BUFSIZE,"100 days later :%Y-%m-%d",tm);

        puts(buf);

 

exit(0);

}

 

三、进程环境

[进程终止方式]

1、main函数

int main(int argc, char *argv[])

argc是命令行参数的数目,argv是指向参数的各个指针所构成的数组

 

2、进程的终止

正常终止:

1从main函数返回;

注意:在 main 函数中调用 return 0 和 exit(0)是等价的

 

2调用exit;

使当前进程正常终止:void exit(int status);

 

3调用_exit或_Exit;

void _exit(int status);

void _Exit(int status);

注意:exit 函数会调用 fclose 关闭所有打开的流,并且会调用由 atexit 安装的函数,另外两个函数会直接进入内核,不会清理缓存。

 

4最后一个线程从其启动例程返回;

 

5最后一个线程调用pthread_exit。

 

异常终止:

1调用abort;

2接到一个信号并终止;

3最后一个线程对其取消请求作出响应。

 

钩子函数:atexit()

int atexit(void (*function)(void));

安装若干个在调用 exit 函数时候调用的函数 function,注册一个在正常进程终止时调用的函数。

注意:每个进程可以安装多达 32 个函数,同一个函数也可以被安装多次,执行的顺序和安装的顺序相反。

 

[钩子函数]

#include<stdlib.h>

#include<stdio.h>

 

static void f1(void)

{

    puts("f1() is working!");

}

 

static void f2(void)

{

    puts("f2() is working!");

}

 

static void f3(void)

{

    puts("f3() is working!");

}

 

int main()

{

    puts("Begin!");

    atexit(f1);

    atexit(f2);

    atexit(f3);

    puts("End!");

    exit(0);

}

/*****************

 Begin!

 End!

 f3() is working!

 f2() is working!

 f1() is working!

******************/

 

3、[命令行参数的分析]

 

解析命令行参数:int getopt(int argc, char * const argv[],const char *optstring);

 

[命令行实例2]

//解析时间

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <time.h>

 

#define SIZE 1024

 

int main(int argc,char **argv)

{

struct tm *tm;

time_t stamp;

char buf[SIZE];

int ch;

char fmt[SIZE] = {'\0'};//格式串 空串

FILE *fp = stdout;

 

stamp = time(NULL);//获取时间戳

tm = localtime(&stamp);//转换为结构体形式

 

while(1)

{

ch = getopt(argc,argv,"-y:mdH:MS");

//解析命令行参数-y:mdH:MS -表示识别非选项的传参  :表示这个字母在终端上使用传参的话,它有自己的参数,这叫带参数的选项

if(ch < 0)

break;

 

switch(ch)

{

case 1:

if(fp == stdout)

{

fp = fopen(argv[optind-1],"w");

if(fp == NULL)

{

perror("fopen()");

fp = stdout;

}

}

break;

case 'y':

if(strcmp(optarg,"2") == 0)

strncat(fmt,"%y ",SIZE);

else if(strcmp(optarg,"4") == 0)

strncat(fmt,"%Y ",SIZE);

else

fprintf(stderr,"Invalid argument of -y\n");

break;

 

case 'm':

strncat(fmt,"%m ",SIZE);

                break;

 

case 'd':

strncat(fmt,"%d ",SIZE);

                break;

 

case 'H':

 if(strcmp(optarg,"12") == 0)

                     strncat(fmt,"%I(%P) ",SIZE);

                  else if(strcmp(optarg,"24") == 0)

                         strncat(fmt,"%H ",SIZE);//向fmt中连进去一个大小为SIZE的%H,覆盖fmt中的'\0'。

                      else

                         fprintf(stderr,"Invalid argument of -H\n");

                break;

 

case 'M':

strncat(fmt,"%M ",SIZE);//向fmt中连进去一个大小为SIZE的%M,覆盖fmt中的'\0'。

                break;

 

case 'S':

strncat(fmt,"%S ",SIZE);//向fmt中连进去一个大小为SIZE的%S,覆盖fmt中的'\0'。

                break;

 

default:

break;

}

}

 

strncat(fmt,"\n",SIZE);

strftime(buf,SIZE,fmt,tm);//按照fmt格式从tm中拿出内容放到大小为SIZE的buf中。

fputs(buf,fp);

 

if(fp != stdout)

fclose(fp);

 

exit(10);

}

4、[环境变量]

每个进程都有一组环境变量,进程的环境变量继承于父进程

指向进程环境表的指针是 char **environ

环境表是一个指针数组,数组中的每一个指针都指向一个字符串(环境变量)

查看环境变量:export

KEY = VAILE

environ存放所有的环境变量

 

1>获得环境变量:char *getenv(const char *name);

返回值:指向与name关联的value的指针;若未找到,返回NULL

注意:如果在环境变量当中没有 name,那么该函数可能会导致段错误。

(获取环境变量)

#include <stdio.h>

#include <stdlib.h>

extern char **environ;

int main()

{

puts(getenv("PWD"));//获取当前路径

/*

int i;

for(i = 0 ; environ[i] != NULL ; i++)//获取所有环境变量

puts(environ[i]);

*/

exit(0);

}

 

2>修改或添加一个环境变量的值:int putenv(char *string);

返回值:成功,返回0;出错,返回非0.

putenv取形式为name=value的字符串,将其放到环境表中。如果name已经存在,则先删除其原来的定义。

 

3>int setenv(const char *name, const char *value, int overwrite);

返回值:成功,返回0;出错返回-1.

name表示环境变量的名字 name存在相当与add,name不存在相当于change  value=name   overwrite表示是否覆盖。

setenv将name设置为value,如果在环境中name已经存在,那么:

(a)若overwrite非0,则首先删除其现有的定义;

(b)若overwrite为0,则不删除其现有定义(name不能设置为新的value,而且也不出错)。

 

注意:用 putenv 添加或者修改环境变量时,系统并不分配空间给 name,只是把 name 添加或者更新到环境表中,

所以只要修改了 name 指向的字符串就修改了环境变量,如果 name指向的空间是在某个函数的栈中分配的,一旦函数返回就可能出现问题.

 

4>删除环境变量

int unsetenv(const char *name);

返回值:成功,返回0;出错返回-1.

 

5、c程序的存储空间布局

[程序空间和手工装载库]

pmap(1)

内存分配

void *malloc(size_t size);

void free(void *ptr);

void *calloc(size_t nmemb, size_t size);

void *realloc(void *ptr, size_t size);

 

6、库

动态库

静态库

手工装载库

 

void *dlopen(const char *filename, int flags);

filename表示要手工装载库的名字 flags表示打开的模式

返回值:成功返回一个非空指针;出错返回NULL。

 

int dlclose(void *handle);

返回值:成功返回0;出错返回非零值。

 

为动态加载的应用程序界面中的函数获取错误诊断:char *dlerror(void);

 

在共享对象或可执行文件中获得一个符号的地址:void *dlsym(void *handle, const char *symbol);

返回值:成功,返回与符号关联的地址。失败时,返回NULL。

 

[手工装载库并打印cosine2.0]      

#include <stdio.h>     

#include <stdlib.h>      

#include <dlfcn.h>      

#include <gnu/lib-names.h>  

int main(void)

       {

           void *handle;

           double (*cosine)(double);

           char *error;

           handle = dlopen(LIBM_SO, RTLD_LAZY);

           if (!handle) {

               fprintf(stderr, "%s\n", dlerror());

               exit(EXIT_FAILURE);

           }

           dlerror();    /* Clear any existing error */

           cosine = (double (*)(double)) dlsym(handle, "cos");

           //*(void **) (&cosine) = dlsym(handle, "cos");

           error = dlerror();

           if (error != NULL) {

               fprintf(stderr, "%s\n", error);

               exit(EXIT_FAILURE);

           }

           printf("%f\n", (*cosine)(2.0));

           dlclose(handle);

           exit(EXIT_SUCCESS);

       }

 

7、函数跳转

goto不能跨函数跳转

长跳转

用 setjmp 设立一个标志,用 longjmp 跳到该标志处,setjmp 调用时返回 0,longjmp 的调用

会使 setjmp 再一次返回,返回值是 val。

 

1>设置跳转点:int setjmp(jmp_buf env);

返回值:若直接调用,返回0;若从longjmp返回,则为非0.

 

2>返回跳转点:void longjmp(jmp_buf env, int val);

env为设置的跳转点,val为带会的东西。

注意:longjmp 会涉及到变量的回滚,在不指定优化条件的前提下,自动变量、静态变量、易失性变量、寄存器变量、全局变量都不会回滚(因为这些变量都放到内存中),

但是在指定了-O3 优化的情况下,自动变量和寄存器变量会被放到寄存器中,因此会回滚。

注意:如果多次用同一个 env 调用 setjmp 函数,则最后一次有效。

 

(跳转实例)

#include <stdio.h>

#include <stdlib.h>

#include <setjmp.h>

 

static jmp_buf save;

 

void d(void)

{

    printf("[%s]Begin\n",__FUNCTION__);

    printf("[%s]Jump now!\n",__FUNCTION__);

    longjmp(save,6);

    printf("[%s]End\n",__FUNCTION__);

}

 

void c(void)

{

    printf("[%s]Begin\n",__FUNCTION__);

    printf("[%s]call d()\n",__FUNCTION__);

    d();

    printf("[%s]d() returned.\n",__FUNCTION__);

    printf("[%s]End\n",__FUNCTION__);

}

 

void b(void)

{

    printf("[%s]Begin\n",__FUNCTION__);

    printf("[%s]call c()\n",__FUNCTION__);

    c();

    printf("[%s]c() returned.\n",__FUNCTION__);

    printf("[%s]End\n",__FUNCTION__);

}

 

void a(void)

{

int ret;

printf("[%s]Begin\n",__FUNCTION__);

 

ret = setjmp(save);

if(ret == 0)//set

{

printf("[%s]call b()\n",__FUNCTION__);

b();

printf("[%s]b() returned.\n",__FUNCTION__);

}

else

{

printf("[%s]Jumped back here with code %d.\n",__FUNCTION__,ret);

}

    printf("[%s]End\n",__FUNCTION__);

}

 

int main()

{

printf("[%s]Begin\n",__FUNCTION__);

printf("[%s]call a()\n",__FUNCTION__);

a();

printf("[%s]a() returned.\n",__FUNCTION__);

printf("[%s]End\n",__FUNCTION__);

 

exit(0);

}

 

/*

[main]Begin

[main]call a()

[a]Begin

[a]call b()

[b]Begin

[b]call c()

[c]Begin

[c]call d()

[d]Begin

[d]Jump now!

[a]Jumped back here with code 6.

[a]End

[main]a() returned.

[main]End

*/

 

8、资源的获取及控制

 

获得进程资源限制:int getrlimit(int resource, struct rlimit *rlim);

修改进程资源限制:int setrlimit(int resource, const struct rlimit *rlim);

返回值:成功返回0; 出错返回-1,并设置error。

 struct rlimit {

               rlim_t rlim_cur;  /* Soft limit */

               rlim_t rlim_max;  /* Hard limit (ceiling for rlim_cur) */

           };

 

注意: rlim.rlim_cur 是当前的限制,任何进程都可以修改(但必须小于等于 rlim.rlim_max),

rlim.rlim_max 是一个限制的最大值,只有超级用户进程才可以提高这个值

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值