加载中…
正文 字体大小:

暑假--学习笔记3

(2014-08-01 10:10:42)
标签:

it

    关于这半个月的学习,我也不知道到底能记住些什么,浑浑噩噩,前几天学长问起,看书情况怎么样?我说,看不进去,想家到不行。之后,我又想想,快回家了,再坚持坚持。虽然看书看得浑浑噩噩,但是最基本的api的用法是必须掌握的,不知不觉apue也看到300页。

     前几天,有个学妹问起实际用户ID、有效用户ID、文件所有者的相关内容,这半个月的学习又看到了一个叫做保存的设置用户ID。

    

一、用户标识:

实际用户ID:当用户使用用户名和密码成功登陆到系统后,就唯一地确定了实际用户ID。

有效用户ID:用于系统决定用户对系统资源的访问权限。

保存的设置用户ID:作为有效用户的副本,在执行exec函数后能重新恢复原来的有效用户。

其实前两个我以前已经知道了区别了,第三个是才知道的概念。

附属组ID:如果系统允许一个用户属于多个用户组。“登录时,读/ect/group,寻找列有该用户作为其成员的记录项就可以得到该用户的附属组ID。”


Linux系统中有“口令文件”和“阴影口令”。这两个都是和用户信息密码有关的文件。


口令文件时“/etc/passwd”文件,里面包含着用户信息,各字段用冒号隔开:

注册名:口令:用户标识号:组标识号:用户名:用户主目录:命令解释器。


注册名:用于区分不同的用户。在同一系统中注册名是惟一的。

口令:原来时存放加密口令字,但是把加密口令放在一个人人可读的文件中很不安全,所以此处一般使用“X”表示,如果看到用“*”表示,则表明系统不允许该用户登录了。

命令解释器:包含了一个可执行程序名,它被用作该用户的登录shell。如果存在以sshd为注册名的一行,最后显示为/sbin/nologin,目的是阻止任何人以sshd的名义登录到该系统。


还有一个叫做阴影口令,一般是/etc/shadow/文件,只有root用户拥有读权限,其他用户不拥有,弥补了口令文件 人人可读 的缺陷。阴影口令文件里的字段也是由冒号隔开,第二个字段就是加密口令。加密口令是经“单向”加密算法处理过的用户口令副本,“单向”就保证了不能用加密口令猜到原来的口令。阴影口令文件不是一般用户可以读取的,只有几个少数的程序需要并且可以访问阴影口令,比如login(1)和passwd(1)。

    

   然后还学到一些api:

 

   暑假--学习笔记3

   

  暑假--学习笔记3


           暑假--学习笔记3


           暑假--学习笔记3
            
            里面出现了三个结构体;分别是:struct passwd, struct spwd, struct group。一般是在使用时在函数内部定义静态变量,调用通过id或者名称获得结构体的函数中填写这些结构体,只要调用任一相关函数,该静态变量就要发生变化。

  对于关于附属组信息的三个函数中,第三个函数initgroups是初始化附属组表。所以该函数可以是由getgrent、setgrent和endgrent三个函数来读取整个文件,然后根据文件里的内容,再调用setgroups函数(所以也只有超级用户才能调用)之后,就可以对username确定其组的成员关系。同时,basegid是口令文件中的组ID。
          
  二、关于进程:

在学习怎么创建进程之前,给我们铺垫了很多。比如说环境表、共享库和C程序的存储空间布局,存储空间的分配、一些退出函数和C程序的启动。


main函数是有原型的:int main(int argc, char *argv[]);

argc叫做命令行参数的数目、argv是指向参数的各个指针所构成的数组。

内核在执行一个C程序时,会调用一个exec函数来读生成的可执行文件和做一些初始化工作,具体的我没弄清。然后在调用main函数之前,会调用一个启动例程(_start),再做一些初始化工作,然后启动例程获得命令行参数和环境变量来调用main()函数。所以可执行程序文件的起始地址是启动例程的地址,说main()是程序的入口,也不准确了,程序的入口是启动例程。同时,main()也不是必须的了,其实自己可以让启动例程去调用其他函数,而不一定是main()就可以了。


 

上面说到环境变量,其实每个进程都会有一个环境表。而环境表是一个字符指针数组。全局变量environ(环境指针)包含了该指针数组的地址:extern char **environ。


                   暑假--学习笔记3

 

 环境的访问是通过:


                暑假--学习笔记3

     这些函数在修改环境表时是有些复杂的,因为环境变量在经典的c程序的存储空间布局上位于栈顶之上

                              暑假--学习笔记3


        由图上可以看出,环境变量是位于栈顶之上的,它的存储空间不能再向高地址方向扩展,并且也不能向低地址方向扩展,所以该空间的长度不能再增加。如果是在环境表中删除一个字符串是很简单的,但是如果增加或者修改一个字符串就有点困难了。如果是增加一个字符串或者修改原先值使其边长了,此时一般会用到malloc函数。然后使环境表中针对name的指针指向新分配的区域或者environ指向新指针表。

 

     进程的终止分为五种正常终止和三种异常终止。正常终止是从main函数返回,或者调用退出函数等。异常终止就是调用abort函数,接受信号或者最后一个线程对取消请求做出响应。


      书上介绍了这么些api,用例很少,但是它还是给出了用getpwent函数来实现getpwnam的一个例子。

 

#include 

#include 

#include 

#include 

#include 

 

 

struct passwd *mygetpwnam(const char *name)

{

struct passwd *ptr;

 

//这是一种自我保护性的措施,以便确保如果调用者在此之前已经调用getpwent打开了有关文件情况下,反绕有关文件

//使它们定位到文件开始处

setpwent();

 

//第一次调用时,getpwent打开它所使用的各个文件,然后就返回口令文件的下一项记录

while ((ptr getpwent()) != NULL){

if (strcmp(name, ptr->pw_name) == 0){

break;

}

}

 

//getpwent函数读取完文件后,并不会关闭文件

//endpwent用来关闭文件。

endpwent();

 

return ptr;

}

 

 

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

{

struct passwd *ptr;

 

if (argc != 2){

printf("arguements error!");

exit(0);

}

 

if ((ptr mygetpwnam(argv[1])) != NULL){

printf("%6s", ptr->pw_name);

printf("m", ptr->pw_uid);

printf("m", ptr->pw_gid);

printf("s", ptr->pw_shell);

}else{

printf("not found %s", argv[1]);

}

 

printf("\n");

return 0;

}



运行结果:

暑假--学习笔记3

 

    这篇博客提到的每一个点都值得我再深入了解和学习。今日只是完完全全简单总结了一些些概念。


       

 

0

阅读 评论 收藏 转载 喜欢 打印举报
已投稿到:
  • 评论加载中,请稍候...
发评论

    发评论

    以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

      

    新浪BLOG意见反馈留言板 不良信息反馈 电话:4006900000 提示音后按1键(按当地市话标准计费) 欢迎批评指正

    新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

    新浪公司 版权所有