• 《Linux/Unix系统编程手册》读书笔记6


    《Linux/Unix系统编程手册》读书笔记 目录

    第9章

    这章主要讲了一堆关于进程的ID。实际用户(组)ID、有效用户(组)ID、保存设置用户(组)ID、文件系统用户(组)ID。和辅助组ID。

    实际用户ID决定执行者是谁

    有效用户ID决定该进程执行时获取的文件权限。PS:有效用户ID为0的进程拥有超级用户的所有权限。

    认识保存设置用户ID(saved set-user-ID)的时候先来看看设置用户ID(set-user-ID)(对于文件的)。

    如果可执行文件设置了设置用户ID,当该文件执行的时候会将该进程的有效用户ID设置为执行文件的用户ID。

    例如当某个执行文件的用户ID为root,而且设置了设置用户ID,那么如果某用户(非root)运行该文件的时候,该进程的有效用户ID就会变成root,也就是0,从而获取超级进程用户权限。例如passwd,ping。这两个文件的所属都属于root,但是这两个文件可以不以root来执行。通过ls -l可以看到它们设置了set-user-ID位。

    lancelot@debian:~$ ls -l /bin/ping
    -rwsr-xr-x 1 root root 36136  4月 13  2011 /bin/ping
    lancelot@debian:~$ ls -l /usr/bin/passwd 
    -rwsr-xr-x 1 root root 51096  5月 26  2012 /usr/bin/passwd

    然后我们来看一个详细的例子:

    一个可执行文件check_password要根据/etc/shadow来检查密码是否正确,但是访问/etc/shadow需要权限。

    lancelot@debian:~/Code/tlpi$ ls -l check_password
    -rwxr-xr-x 1 lancelot lancelot 16031  4月 25 22:50 check_password
    lancelot@debian:~/Code/tlpi$ ./check_password 
    Username: lancelot
    ERROR: no permissong to read shadow password file

    然后我们先修改它的用户ID,再设置设置用户ID权限位。然后来看看运行结果。

    lancelot@debian:~/Code/tlpi$ sudo chown root check_password
    lancelot@debian:~/Code/tlpi$ sudo chmod u+s check_password
    lancelot@debian:~/Code/tlpi$ ls -l check_password
    -rwsr-xr-x 1 root lancelot 16031  4月 25 22:50 check_password
    lancelot@debian:~/Code/tlpi$ ./check_password 
    Username: lancelot
    Password: 
    Successfully authenticated: UID=1000

    好了,现在来看看保存设置用户ID了,其实就是进程的有效用户ID的副本。

    文件系统用户ID决定文件系统操作的权限。其值通常与有效用户ID相同。PS:当有效用户ID发生改变,文件系统用户ID也会紧接着发生改变(变成相同的值)。

    获取实际用户和有效用户ID

    1 #include <unistd.h>
    2 
    3 uid_t getuid(void);      //返回调用进程的实际用户ID
    4 
    5 uid_t geteuid(void);    //返回调用进程的有效用户ID
    6 
    7 gid_t getgid(void);      //返回调用进程的实际组ID
    8 
    9 gid_t getegid(void);   //返回调用进程的有效组ID

    修改有效ID:

    1 #include <unistd.h>
    2 
    3 int setuid(uid_t uid);
    4 
    5 int setgid(gid_t gid);

    成功修改返回0,失败返回-1。

    PS:非特权进程(有效ID为0)调用修改有效ID时,只能修改进程的有效用户ID(将其值设置为实际用户ID和保存设置用户ID)。当特权进程调用修改有效ID时,实际用户ID、有效用户ID和保存设置用户ID均会设置为uid的值。

    1 #include <unistd.h>
    2 
    3 int seteuid(uid_t euid);
    4 
    5 int setegid(gid_t egid);

    成功修改返回0,失败返回-1。

    PS:非特权进程仅能将有效用户ID设置为实际用户ID或者保存设置用户ID。特权进程可以将有效用户ID设置为任意值。

    修改实际ID和有效ID

    #include <unistd.h>
    
    int setreuid(uid_t ruid, uid_t euid);
    
    int seregid(gid_t rgid, gid_t egid);

    成功修改返回0, 失败返回-1。

    第一个参数为新的实际ID,第二个参数为新的有效ID。如果只修改其中一个,可以将另一个的值设置为-1。

    获取实际、有效和保存设置ID:

    1 #define _GNU_SOURCE
    2 #include <unistd.h>
    3 
    4 int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid);
    5 
    6 int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid);

    成功获取返回0,失败返回-1。

    修改实际、有效和保存设置ID:

    1 #define _GNU_SOURCE
    2 #include <unistd.h>
    3 
    4 int setresuid(uid_t ruid, uid_t euid, uid_t suid);
    5 
    6 int getresgid(gid_t rgid, gid_t egid, gid_t sgid);

    成功修改返回0, 失败返回-1。

    如果不想修改的ID,可以设置为-1。

     获取和修改文件系统ID:

    1 #inlcude <sys/fsuid.h>
    2 
    3 int setfsuid(uid_t fsuid);
    4 
    5 int setfsgid(gid_t fsgid);

    --------------------------------------------------------省略辅助组ID----------------------------------------------

    第10章

    这章主要讲了时间的概念。时间分为两种类型:1、真实时间;2、进程时间。

    真实时间:

    一、日历时间,用于对记录或文件打上时间戳。

    二、流逝时间或挂钟时间,用于需要周期性操作或定期从外部输入设备进行度量的程序。

    日历时间:

    UNIX系统内部对时间的表示方式是自1970年1月1日早晨零点以来的秒数。

    1 #include <time.h>
    2 
    3 time_t time(time_t *timep);

    返回自1970年1月1日早晨零点以来的秒数,出现错误返回-1。

    如果timep为NULL,直接返回自1970年1月1日早晨零点以来的秒数,如果不为NULL,还会讲秒数置于timep所指向的位置。

    获取到秒数后就要通过一些函数将秒数转成人类可读的格式。

    通过ctime:

    1 #include <time.h>
    2 
    3 char *ctime(const time_t *timep);

    返回指向静态分配的字符串的指针,出现错误返回NULL

    1 #include <stdio.h>
    2 #include <time.h>
    3 
    4 int main(int argc, char *argv[]){
    5     time_t t = time(NULL);
    6     printf("%s
    ", ctime(&t));
    7     return 0;
    8 }

    结果:

    1 lancelot@debian:~/Code/tlpi$ ./a.out 
    2 Sat Apr 26 09:33:27 2014

    有时候我们不仅需要将时间转成可打印的格式,还需要将时间分解成很多独立字段。这个时候就需要用到gmtime()或者localtime()。

    1 #include <time.h>
    2 
    3 struct tm *gmtime(const time_t *timep);
    4 
    5 struct tm* localtime(const time_t *timep);

    返回指向静态分配的字符串的指针,出现错误返回NULL。gmtime返回的是对UTC的分解时间,localtime返回的是对系统本地时间的分解时间。

    如果现在存在一个分解时间,可以通过mktime来输出其对应的秒数。

    1 #include <time.h>
    2 
    3 time_t mktime(struct tm *timeptr);

    返回自1970年1月1日早晨零点以来到分解时间的秒数,出现错误返回-1。

    我们还可以对分解时间进行转换,转换成可打印时间。

    1 #include <time.h>
    2 
    3 char *asctime(const struct tm *timeptr);

    返回指向静态分配的字符串的指针,错误返回NULL。

    ------昨晚睡觉前开始写的。。。。感觉好像搞懂了那一对关于进程的ID。。。。。还是挺开心的

    ------在看到别人的收获的时候,还要看到别人付出的血汗。正因为你不够别人勤奋,所以你才落后别人

    ------好好努力,为了9月份的校招!!!!!!!!还有时间!!!!!!!

  • 相关阅读:
    MySQL Replication主从复制
    使用Amoeba 实现MySQL DB 读写分离
    Amoeba For MySQL入门:实现数据库水平切分
    11条理由告诉你,为什么你的网站不卖座
    很有用的观察者设计模式
    Apache + Tomcat集群配置详解 (1)
    Nginx+tomcat配置负载均衡
    JSON-RPC轻量级远程调用协议介绍及使用
    nginx的upstream目前支持5种方式的分配
    rpc远程过程协议调用
  • 原文地址:https://www.cnblogs.com/alan-forever/p/3690320.html
Copyright © 2020-2023  润新知