1 umask
1.1 对应系统调用sys_umask,源码实现在/kernel/sys.c中,SYSCALL_DEFINE1(umask, int, mask)
利用传进来的参数mask对当前进程的文件结构体掩码进行赋值:xchg(¤t->fs->umask, mask & S_IRWXUGO);
task_struct结构体中fs的结构如下:
struct fs_struct {
int users;
spinlock_t lock;
seqcount_t seq;
int umask;
int in_exec;
struct path root, pwd;
};
1.2 作用描述
举一个使用位置来说,在文件系统的inode节点支持的操作函数atomic_open中被用于mode &= ~current_umask(),屏蔽掉某些权限位。
1.3 示例
#include<stdio.h>
#include<fcntl.h>
#include<stdlib.h>
int main(int argc, char *argv[]){
int fd = fd = open("./huha0", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH);
if(fd < 0){
printf("open error!\n");
exit(-1);
}
close(fd);
umask(0);
fd = open("./huha1", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH);
if(fd < 0){
printf("open error!\n");
exit(-1);
}
close(fd);
umask(S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH);
fd = open("./huha2", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH);
if(fd < 0){
printf("open error!\n");
exit(-1);
}
close(fd);
return 0;
}
结果如下:
备注:系统默认的umask是S_IWGRP | S_IWOTH.
2 getrlimt
2.1 对应系统调用sys_getrlimt,为了获得进程可以使用的各类资源的上限值,原型如下:int getrlimit(int resource, struct rlimit *rlim),当resource是RLIMIT_NOFILE的时候,可以获得进程可以打开的文件的最大个数。函数成功返回0,失败返回-1.
rlimit的结构如下:
struct rlimit {
rlim_t rlim_cur;
rlim_t rlim_max;
};
rlimit_t是unsigned long类型的别名,rlim_cur代表的是内核对进程资源的限制,rlim_max是硬件对进程资源的最大支持。
2.2 示例
#include<stdio.h>
#include<sys/resource.h>
#include<stdlib.h>
int main(int argc, char *argv[]){
int fd0, fd1, fd2;
struct rlimit re;
if(getrlimit(RLIMIT_NOFILE, &re) < 0){
printf("getrlimit error!\n");
exit(-1);
}
printf("max fd value which parent could open under the rule of kernel = %ld\n", re.rlim_cur);
printf("max fd value which parent could open under the rule of hardware = %ld\n", re.rlim_max - 1);
printf("1: parent can printf!\n");
int fd;
for(fd = 0; fd < re.rlim_cur; fd ++){
close(fd);
}
printf("2: parent can printf!\n");
return 0;
}
结果如图:
3 chdir getcwd
3.1 chdir可以改变进程当前的工作目录,getcwd可以获得进程当前的工作目录。
3.2 示例
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#define MAX_PATH 100
int main(int argc, char *argv[]){
char buf[MAX_PATH];
getcwd(buf, sizeof(buf));
printf("current dir = %s\n", buf);
chdir("/tmp");
getcwd(buf, sizeof(buf));
printf("current dir = %s\n", buf);
return 0;
}
结果如下图:
4 daemon进程创建
4.1 daemon进程是一类特殊的进程,特殊之处在于以下几点:(1)没有对应的终端可以输入输出,即文件句柄的0、1、2不对应于终端输入、终端输出、终端错误;(2)进程的生命周期与终端进程bash脱离关系,即一般使用bash启动的进程会随着bash进程的退出而终止,而daemon进程虽然也可能是通过终端启动,但其生命周期与终端进程bash脱离关系;(3)daemon进程的父进程一般是init进程,除了init进程启动的daemon进程外,其他通过使用终端bash进程启动的daemon会在终端bash进程退出后成为孤儿进程,之后内核将其挂在init进程的子进程链表中。
daemon进程的创建有很多方法,此处采用的方法如下:启动父进程 -> 父进程fork子进程A -> 进程A脱离旧的终端会话,产生新的终端会话,成为新终端会话的首进程 -> 进程A关闭继承自父进程的所有文件句柄,与终端脱离关系 -> 由于进程A是终端会话首进程,所以其可以再次打开一个新的终端,于是此处,进程A再次fork子进程B -> 此时,进程B不再是终端会话的首进程,不可以打开新的终端,将进程B的0、1、2分别设置为指向文件/dev/null、/tmp/out.log、/tmp/error.log的句柄,改变当前工作目录为/tmp -> 进程B便是我们的创建的daemon进程。
4.2 示例
#include<stdio.h>
#include<stdlib.h>
#include<fcntl.h>
#include<string.h>
#include<unistd.h>
#include<sys/resource.h>
int main(int argc, char *arv[]){
int fd;
pid_t a, b;
a = fork();
if(a < 0){
printf("fork error!\n");
exit(-1);
}else if(a > 0){
printf("parent: succ to fork child!\n");
printf("parent: exit!\n");
exit(0);
}
printf("A: I'm here!\n");
printf("A: I'm changing session ID!\n");
if(setsid() < 0){
printf("A: setsid error!\n");
printf("A: bye!\n");
exit(0);
}
printf("A: I'm going to close all the file handles!\n\
So, You all won't see me again!\n\
But maybe you can find my child B's words!\n");
struct rlimit re;
if(getrlimit(RLIMIT_NOFILE, &re) < 0){
printf("A: I can not getrlimit()!\n");
printf("A: bye!\n");
exit(0);
}
for(fd = 0; fd < re.rlim_cur; fd ++){
close(fd);
}
b = fork();
if(b < 0){
printf("A: anyway, you can not see error!\n");
exit(0);
}else if(b > 0){
exit(0);
}
umask(S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH);
int fd0, fd1, fd2;
fd0 = open("/dev/null", O_RDWR);
fd1 = open("/tmp/out.log", O_RDWR | O_CREAT, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH);//for test
fd2 = open("/tmp/error.log", O_RDWR | O_CREAT, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH);//for test
if(fd0 < 0 || fd1 < 0 || fd2 < 0){
printf("B: sorry, you can not see error!\n");
exit(0);
}
printf("B: CaN yOu Find mE?\n");
printf("B: I am your daemon!\n");
char buf[1000];
getcwd(buf, sizeof(buf));
printf("B: current pwd = %s\n", buf);
chdir("/tmp");
getcwd(buf, sizeof(buf));
printf("B: current pwd = %s\n", buf);
int i =0;
while(++ i){
printf("B: I am going to sleep %d sec.\n", i);
sleep(i);
sprintf(buf, "B: maybe I should output something like error!\tid = %d, con = 00000110010.\n", i);
write(fd2, buf, strlen(buf));
}
return 0;
}
结果如图: