用户 ID和组 ID 的内容已经在好几章中出现过了。之前都没有讲到,现在放到一起总结。

一、用户 ID 和 组 ID 回顾

1、我们在APUE 第 4、6、8 章,都有涉及到。

其中我们用到的地方:

(1)修改文件权限

参看:UNIX再学习 -- 文件和目录

chgrp命令 功能:改变文件或目录的属组。
chown 命令 功能:更改某个文件或目录的属主和属组。

# ls -l
总用量 16
-rwxr-xr-x 1 root root 7308 Apr 27 11:28 a.out
-rw-r--r-- 1 root root  422 Apr 27 11:28 test.c

第一个 root 为属主,第二个 root 为属组。当然这里面没有用户 ID,和 组 ID

参看:unix实际用户ID和有效用户ID解析

参看:维基百科 -- chmod 命令

下面解析一下格式所表示的意思。这种表示方法一共有十位:

9 8 7 6 5 4 3 2 1 0
- r w x r - x r - x

第9位表示文件类型,可以为p、d、l、s、c、b和-:
    p表示命名管道文件 
    d表示目录文件 
    l表示符号连接文件 
    -表示普通文件 
    s表示socket文件 
    c表示字符设备文件 
    b表示块设备文件
第8-6位、5-3位、2-0位分别表示文件所有者的权限,同组用户的权限,其他用户的权限,其形式为rwx:
    r表示可读,可以读出文件的内容
    w表示可写,可以修改文件的内容
    x表示可执行,可运行这个程序
    没有权限的位置用-表示

如果一个文件被设置了 SUID 或 SGID 位,会分别表现在所有者或同组用户的权限的可执行位上。例如:
    -rwsr-xr-x 表示SUID和所有者权限中可执行位被设置
    -rwSr--r-- 表示SUID被设置,但所有者权限中可执行位没有被设置
    -rwxr-sr-x 表示SGID和同组用户权限中可执行位被设置
    -rw-r-Sr-- 表示SGID被设置,但同组用户权限中可执行位没有被设置
其实在UNIX的实现中,文件权限用12个二进制位表示,如果该位置上的值是
表示有相应的权限:

11 10 9 8 7 6 5 4 3 2 1 0
S G T r w x r w x r w x

第11位为SUID位,第10位为SGID位,第9位为sticky位,第8-0位对应于上面的三组rwx位。
上面的-rwsr-xr-x的值为: 1 0 0 1 1 1 1 0 1 1 0 1
-rw-r-Sr--的值为: 0 1 0 1 1 0 1 0 0 1 0 0

(2)/etc/passwd 

# cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
tarena:x:1000:1000:tarena,,,:/home/tarena:/bin/bash  

其中 超级用户 root 的用户 ID 为 0,组 ID 也为 0 。而我所用的 普通用户 tarena 用户 ID 为 1000,组 ID 为 1000 。

(3)函数 stat

stat 结构体中的 st_uid、st_gid 即用户 ID 和组 ID
struct stat {  dev_t     st_dev;     /* ID of device containing file */  ino_t     st_ino;     /* inode number */  mode_t    st_mode;    /* protection */  nlink_t   st_nlink;   /* number of hard links */  uid_t     st_uid;     /* user ID of owner */  gid_t     st_gid;     /* group ID of owner */  dev_t     st_rdev;    /* device ID (if special file) */  off_t     st_size;    /* total size, in bytes */  blksize_t st_blksize; /* blocksize for file system I/O */  blkcnt_t  st_blocks;  /* number of 512B blocks allocated */  time_t    st_atime;   /* time of last access */  time_t    st_mtime;   /* time of last modification */  time_t    st_ctime;   /* time of last status change */  };  

(4)口令文件相关函数

参看:UNIX再学习 -- 系统数据文件和信息

函数 getpwuid 和 getpwnam  
函数 getpwent、setpwent 和 endpwent
可用于查看 用户 ID 和 组 ID

(5)ps 指令部分

参看:UNIX再学习 -- ps、top、kill 指令
其中各列含义如下:
USER    用户名
UID       用户ID(User ID)
# ps lax
F   UID   PID  PPID PRI  NI    VSZ   RSS WCHAN  STAT TTY        TIME COMMAND
4     0     1     0  20   0   3612  2064 poll_s Ss   ?          0:01 /sbin/init
1     0     2     0  20   0      0     0 kthrea S    ?          0:00 [kthreadd]
1     0     3     2  20   0      0     0 run_ks S    ?          0:01 [ksoftirqd/0]
5     0     5     2  20   0      0     0 worker S    ?          0:01 [kworker/u:0]

二、获取调用进程用户 ID 和 组 ID

当一个用户通过合法的用户名和口令登录系统以后,系统就会为它启动一个 shell 进程,shell 进程的实际用户 ID 和实际组 ID 就是该登录用户的用户 ID 和组 ID。该用户在 shell 下启动的任何进程都是 shell 进程的子进程,自然也就继承了 shell 进程的实际用户 ID 和实际组 ID。

1、获取调用进程的实际用户 ID 和实际组 ID

#include <unistd.h>
#include <sys/types.h>
uid_t getuid(void);
gid_t getgid(void);
分别返回调用进程的实际用户ID 和实际组 ID

(1)示例说明

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>int main (void)
{printf ("uid = %d\n", getuid ());printf ("gid = %d\n", getgid ());return 0;
}
输出结果:
uid = 0
gid = 0我用的是超级用户 root  用户ID为 0,组 ID 为 0 

一个进程的用户和组身份决定了它可以访问哪些资源,比如读、写或者执行某个文件。但真正被用于权限验证的并不是进程的实际用户 ID和实际组 ID,而是其有效用户ID 和有效组 ID一般情况下,进程的有效用户 ID和有效组 ID 就取自其实际用户 ID 和实际组 ID,二者是等价的。

2、获取调用进程的有效用户 ID 和有效组 ID

#include <unistd.h>
#include <sys/types.h>
uid_t geteuid(void);
gid_t getegid(void);
分别返回调用进程的有效用户ID 和有效组 ID

(1)示例说明

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>int main (void)
{printf ("euid = %d\n", geteuid ());printf ("egid = %d\n", getegid ());return 0;
}
输出结果:
euid = 0
egid = 0

三、设置用户 ID 位和设置组 ID 位

如果用于启动进程的可执行文件带有设置用户 ID 位(SUID)和(或)设置组 ID 位(SGID),那么该进程的有效用户 ID 和(或)有效组 ID 就不再取自其实际用户 ID 和(或)实际组 ID,而是取自可执行文件的拥有者用户 ID 和(或)组 ID

1、什么是设置用户 ID 位 和设置组 ID 位

参看:“实际用户ID”、“有效用户ID”和“保存的设置用户ID”三个术语的区别是什么?
例如:
# ls -la test
-rwsrwsr-x 1 root root 7314 Apr 27 16:10 test

其中第一个 s 为设置用户 ID 位SUID),第二个 s 为设置组 ID 位SGID
设置方法:
第一种:采取字符设置
sudo chmod u+s test   设置SUID位
sudo chmod g+s test   设置SGID位
sudo chmod u-s test   去掉SUID设置
sudo chmod g-s test   去掉SGID设置

第二种:采用数字方式设置:
在一般文件权限设置的3位数字前再加上一位数字,成为4位数字。
如果该位为4, 则表示设置 setuid 
如果该位为2, 则表示设置 setgid 
所以,假设文件或目录的原来权限位设置是777,要加上SUID/SGID,如下设置:
chmod 4777 test  设置 SUID 位
chmod 2777 test  设置 SGID 位
chmod 0777 test  去掉 SUID 设置
chmod 0777 test  去掉 SGID 设置

第三种:使用 chmod 函数
再回顾 stat 函数,设置用户 ID 位及设置组 ID 位都包含在文件的 st_mode 值中。这两位可分别用常量 S_ISUID 和 S_ISGID 测试
S_ISUID    0004000   set UID bit
S_ISGID    0002000   set-group-ID bit (see below)  

例如,设置权限 0644:S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH
而设置了 SUID 和 SGID 位。即:S_ISUID | S_ISGID | S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH
举个例子:
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>  int main (void)
{  int res = chmod ("a.txt", S_ISUID | S_ISGID | S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);  if (-1 == res)  perror ("fail to chmod"), exit (1);  execlp ("stat", "stat", "a.txt", NULL);return 0;
}
输出结果:文件:"a.txt"大小:0          块:0          IO 块:4096   普通空文件
设备:801h/2049d    Inode:2107549     硬链接:1
权限:(6644/-rwSr-Sr--)  Uid:(    0/    root)   Gid:(    0/    root)
最近访问:2017-04-27 18:35:15.952010539 +0800
最近更改:2017-04-27 18:35:15.952010539 +0800
最近改动:2017-04-28 09:26:11.755554531 +0800
创建时间:-

而清空使用:~S_ISUID & ~S_ISGID & S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>  int main (void)
{  int res = chmod ("a.txt", ~S_ISUID & ~S_ISGID & S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);  if (-1 == res)  perror ("fail to chmod"), exit (1);  execlp ("stat", "stat", "a.txt", NULL);return 0;
}
输出结果:文件:"a.txt"大小:0          块:0          IO 块:4096   普通空文件
设备:801h/2049d    Inode:2107549     硬链接:1
权限:(0644/-rw-r--r--)  Uid:(    0/    root)   Gid:(    0/    root)
最近访问:2017-04-27 18:35:15.952010539 +0800
最近更改:2017-04-27 18:35:15.952010539 +0800
最近改动:2017-04-28 09:27:11.747554284 +0800
创建时间:-

这个结果是  6644/-rwSr-Sr--, 其中 s 和 S 还是有区别的,上面提到 S 表示 SUID/SGID 被设置,但所有者权限中可执行位没有被设置。因为设置 SUID/SGID 需要有运行权限。如果简单的用 chmod 函数来设置好像还是不行。所以不推荐使用第三种方法。

找出当前设置了 suid 的文件方法:
参看:C语言再学习 -- Linux下find命令用法

# find . -perm -4000 -type f
./a.txt

2、SUID 和 SGID 位 作用
举个例子,用户更改登录密码,是通过运行命令passwd来实现的。最终必须要修改/etc/passwd文件,而passwd的文件的属性是:

# stat /etc/passwd文件:"/etc/passwd"大小:1918          块:8          IO 块:4096   普通文件
设备:801h/2049d    Inode:1076219     硬链接:1
权限:(0644/-rw-r--r--)  Uid:(    0/    root)   Gid:(    0/    root)
最近访问:2017-04-28 09:36:00.775552859 +0800
最近更改:2016-12-01 10:28:54.801942085 +0800
最近改动:2016-12-01 10:28:54.809942031 +0800
创建时间:-

我们可以看到 passwd 文件只有对于 root 用户是可写的,而对于所有的他用户来说都是没有写权限的。 那么一个普通的用户如何能够通过运行 passwd 命令修改这个 passwd 文件呢?为了解决这个问题,SUID/SGID 便应运而生。

当一个程序设置了为SUID位时,内核就知道了运行这个程序的时候,应该认为是文件的所有者在运行这个程序。即该程序运行的时候,有效用户ID是该程序的所有者。
有效用户ID和有效组ID则决定了进程在运行时的权限。内核在决定进程是否有文件存取权限时,是采用了进程的有效用户ID来进行判断的。
虽然你以 tarena t登陆系统,但是当你输入 passwd 命令来更改密码的时候,由于 passwd 设置了 SUID 位,因此虽然进程的实际用户 ID 是 tarena 对应的 ID,但是进程的有效用户 ID 则是 passwd 文件的所有者 root 的 ID,因此可以修改 /etc/passwd 文件
3、有效用户/组 ID 和设置用户/组/ ID 位关系
假设 test 文件的拥有这用户和组都是 root ,且其他用户对该文件可执行权限。
# ls -la test
-rwxr-xr-x 1 root root 7238 Apr 27 15:35 test

而此时我注销root用户,使用隶属于 tarena 组 (GID = 1000)和tarena 用户(UID = 1000)登录系统,运行 test 程序。

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>int main (void)
{printf ("uid = %d\n", getuid ());printf ("gid = %d\n", getgid ());printf ("euid = %d\n", geteuid ());printf ("egid = %d\n", getegid ());return 0;
}
输出结果:
uid = 1000
gid = 1000
euid = 1000
egid = 1000

可以看到进程的有效用户 ID 和实际用户 ID 一样都是 1000,而有效组 ID 也和实际组 ID一样都是 1000。

它们都是取自可执行文件的拥有者用户 ID 和(或)组 ID。
现在 root 用户为 test 文件添加设置用户 ID 位和设置组 ID 位权限位。也必须使用 sudo 普通用户无法修改权限。
设置权限
sudo chmod u+s test
sudo chmod g+s test查看 test 权限
$ ls -la test
-rwsrwsr-x 1 root root 7314  4月 27 16:10 test

使用隶属于 tarena 组和 tarena用户再次运行 test 程序

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>int main (void)
{printf ("uid = %d\n", getuid ());printf ("gid = %d\n", getgid ());printf ("euid = %d\n", geteuid ());printf ("egid = %d\n", getegid ());return 0;
}
输出结果:
uid = 1000
gid = 1000
euid = 0
egid = 0

不难发现,进程的实际用户 ID 和实际组 ID 并没有发生变化,仍然是 1000,但它的有效用户 ID 和有效组 ID 却变成了 0,显然这是 test 文件的拥有者 root 用户 ID 和 组 ID而参与权限判断,决定该进程能做什么不能做什么的恰恰是它的有效用户 ID 和有效组 ID,tarena 用户扮演 root 用户行使权限。

四、实际用户 ID和有效用户 ID 区别

上面我们有简单的介绍了下,实际用户 ID 和有效用户 ID的。
参看:Linux进程的实际用户ID和有效用户ID
(1)实际用户ID和实际用户组ID
标识我是谁。也就是登录用户的uid和gid,比如我的 Linux 以 tarena 登录,在Linux运行的所有的命令的实际用户ID都是 tarena 用户组ID都是 tarena 的gid(可以用id命令查看)。
(2)有效用户ID和有效用户组ID
进程用来决定我们对资源的访问权限。一般情况下,有效用户ID等于实际用户ID,有效用户组ID等于实际用户组ID。当设置用户 ID(SUID)位设置,则有效用户ID等于文件的所有者的uid,而不是实际用户ID;同样,如果设置了设置用户组 ID(SGID)位,则有效用户组ID等于文件所有者的gid,而不是实际用户组ID。
这里介绍一个命令  id ,参看:id 命令
功能:
id 命令可以显示真实有效的用户 ID(UID)和组(ID)。
选项:
-g或--group   显示用户所属群组的ID。
-G或--groups 显示用户所属附加群组的ID。
-n或--name   显示用户,所属群组或附加群组的名称。
-r或--real   显示实际ID。
-u或--user   显示用户ID。
-help   显示帮助。
-version   显示版本信息。

示例:

//超级用户 root 登录
# id
uid=0(root) gid=0(root) 组=0(root)
//普通用户 tarena 登录
$ id
uid=1000(tarena) gid=1000(tarena) 组=1000(tarena),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),109(lpadmin),124(sambashare)

五、更改用户 ID 和更改组 ID

在 UNIX 系统中,特权(如能改变当前日期的表示法)以及访问控制(如能否读、写一个特定文件),是基于用户 ID 和组 ID 的。当程序需要增加特权,或需要访问当前并不允许访问的资源时,我们需要更换自己的用户 ID 和组 ID,使得新 ID 具有合适的特权或访问权限。与此类此,当程序需要降低其特权或阻止对某些资源的访问时,也需要更换用户 ID 或组 ID,新 ID 不具有相应特权或访问这些资源的能力。

1、我们可以用 setuid 函数设置实际用户 ID 和有效用户 ID。可以用 setgid 函数设置实际组 ID 和有效组 ID。

#include <sys/types.h>
#include <unistd.h>
int setuid(uid_t uid);
int setgid(gid_t gid);
两个函数返回值,若成功,返回 0,;若出错,返回-1

(1)函数解析

关于谁能更改 ID 有若干规则。现在先考虑更改用户 ID 的规则(关于用户 ID 我们所说明的一切都适用于组 ID)。

1)若进程具有超级用户特权,则 setuid 函数将实际用户 ID、有效用户 ID 以及保存的设置用户 ID(SUID) 设置为 uid。 
2)若进程没有超级用户特权,但是 uid 等于实际用户 ID 或保存的设置用户 ID,则 setuid 只将有效用户 ID 设置为 uid。不更改实际用户 ID 和保存的设置用户 ID。
3)如果上面两个条件都不满足,则 errno 设置为 EPERM,并返回 -1
在此假定 _POSIX_SAVED_IDS 为真。如果没有提供这种功能,则上面所说的关于保存的设置用户 ID 部分都无效。
关于内核所维护的 3 个用户 ID,还要注意以下几点。
1)只有超级用户进程可以更改实际用户 ID。通常,实际用户 ID 是在用户登录时,由 login 程序设置的,而且决不会改变它。因为 login 是一个超级用户进程,当它调用 setuid 时,设置所有 3 个用户 ID。
2)仅当对程序文件设置了用户 ID 位时,exec 函数才设置有效用户 ID。如果设置用户 ID 位没有设置,exec 函数不会改变有效用户 ID,而将维持其现有值。任何时候都可以调用 setuid ,将有效用户 ID 设置为实际用户 ID 或保存的设置用户 ID。自然地,不能将有效用户 ID 设置为任一随机值。
3)保存的设置用户 ID 是由 exec 复制有效用户 ID 而得到的。如果设置了文件的设置用户 ID 位,则在 exec 根据文件的用户 ID 设置了进程的有效 ID 以后,这个副本就被保存起来了。
总结,更改 3 个用户 ID 的不同方法:

(2)示例说明

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>int main (void)
{printf ("uid = %d\n", getuid ());printf ("gid = %d\n", getgid ());printf ("euid = %d\n", geteuid ());printf ("egid = %d\n", getegid ());if(!setgid(1234))printf("setgid successfully!\n");elseperror ("setgid"), exit (1);if(!setuid(1234))printf("setuid successfully!\n");elseperror ("setuid"), exit (1);printf ("--------------------\n");printf ("uid = %d\n", getuid ());printf ("gid = %d\n", getgid ());printf ("euid = %d\n", geteuid ());printf ("egid = %d\n", getegid ());return 0;
}
输出结果:
uid = 0
gid = 0
euid = 0
egid = 0
setgid successfully!
setuid successfully!
--------------------
uid = 1234
gid = 1234
euid = 1234
egid = 1234

(3)示例解析

考虑一个问题,为什么我先使用 setgid,然后再使用 setuid?
如果反过来会出现 setgid: Operation not permitted。

2、函数 seteuid 和 setegit

#include <unistd.h>
int seteuid(uid_t euid);
int setegid(gid_t egid);
两个函数返回值,若成功,返回 0,失败返回 -1

(1)函数解析

它们类似于 setuid 和 setgid,但是只更改有效用户 ID 和有效组 ID。
一个非特权用户可将其有效用户 ID 设置为实际用户 ID 或保存设置用户 ID。对于一个特权用户则可将有效用户 ID 设置为 uid。这区别于 setuid 函数,它更改所有 3 个用户 ID。

(2)示例说明

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>  int main (void)
{  printf ("uid = %d\n", getuid ());  printf ("gid = %d\n", getgid ());  printf ("euid = %d\n", geteuid ());  printf ("egid = %d\n", getegid ());  if(!setegid(1234))  printf("setegid successfully!\n");  else  perror ("setegid"), exit (1);  if(!seteuid(1234))  printf("seteuid successfully!\n");  else  perror ("seteuid"), exit (1);  printf ("--------------------\n");  printf ("uid = %d\n", getuid ());  printf ("gid = %d\n", getgid ());  printf ("euid = %d\n", geteuid ());  printf ("egid = %d\n", getegid ());  return 0;
}
输出结果:
uid = 0
gid = 0
euid = 0
egid = 0
setegid successfully!
seteuid successfully!
--------------------
uid = 0
gid = 0
euid = 1234
egid = 1234

3、函数 setreuid 和 setregid

#include <sys/types.h>
#include <unistd.h>
int setreuid(uid_t ruid, uid_t euid);
int setregid(gid_t rgid, gid_t egid);
两个函数返回值,若成功,返回 0;若出错,返回 -1

(1)函数解析

函数功能是交换实际用户 ID 和有效用户 ID 的值。
如若其中任一参数的值为 -1,则表示相应的 ID 保持不变。
规则很简单:一个非特权用户总能交换实际用户 ID 和有效 ID。这就允许一个设置用户 ID 程序交换成用户的普通权限,以后又可再次交换用户 ID 权限。POSIX.1 引进了保存的设置用户 ID 特性后,其规则也相应的加强,它允许了一个非特权用户将其有特权用户 ID 设置为 保存的设置用户 ID。

(2)示例说明

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>  int main (void)
{  printf ("uid = %d\n", getuid ());  printf ("gid = %d\n", getgid ());  printf ("euid = %d\n", geteuid ());  printf ("egid = %d\n", getegid ());  if(!setregid(0, 1234))  printf("setregid successfully!\n");  else  perror ("setregid"), exit (1);  if(!setreuid(0, 1234))  printf("setreuid successfully!\n");  else  perror ("setreuid"), exit (1);  printf ("--------------------\n");  printf ("uid = %d\n", getuid ());  printf ("gid = %d\n", getgid ());  printf ("euid = %d\n", geteuid ());  printf ("egid = %d\n", getegid ());  return 0;
}
输出结果:
uid = 0
gid = 0
euid = 0
egid = 0
setregid successfully!
setreuid successfully!
--------------------
uid = 0
gid = 0
euid = 1234
egid = 1234

4、设置不同用户 ID 的各个函数关系

六、APUE 第 8 章未讲部分

第八章是我总结 APUE 以来讲的时间最长的一章,各种小知识点,各种不熟悉,未讲部分一大串,甚是无语。

函数 waitid 未讲
函数 wait3 和 wait4 未讲
竞争条件 未讲
解释器文件 未讲  (后续添加到,shell编程这篇文章里,参看:UNIX再学习 -- shell编程
进程会计 未讲
用户标识 未讲
进程调度 未讲
进程时间 未讲 (这部分查看时间函数,参看:C语言再学习 -- 时间函数

UNIX再学习 -- 用户 ID 和组 ID相关推荐

  1. 8.11 更改用户ID和组ID

    8.11 更改用户ID和组ID 在UNIX系统中,特权是基于用户和组ID的,当程序需要增加特权,或需要访问当前并不允许访问的资源时,我们就需要更换自己的用户ID或组ID. 一般而言,在设计应用程序的时 ...

  2. UNIX再学习 -- 守护进程(转)

    参看:守护进程 一.什么是守护进程 守护进程(Daemon Process),也就是通常说的 Daemon 进程(精灵进程),是 Linux 中的后台服务进程.它是一个生存期较长的进程,通常独立于控制 ...

  3. UNIX再学习 -- 线程

    终于要讲到线程部分,线程和进程让人够头痛的内容. 一.线程概念 老样子,我们还是按我们讲进程时的方式说起,参看:UNIX再学习 -- 进程环境 首先需要了解下,什么是线程. Linux 下的线程,可能 ...

  4. UNIX再学习 -- 进程关系

    APUE 第 10 章信号讲完,回过头来看一下第 9 章的进程关系.终端登录和网络登录部分,我们只讲 Linux 系统的. 一.终端登录 我记得我们讲 root 登录设置时有提到,参看:C语言再学习 ...

  5. UNIX再学习 -- 信号

    终于讲到信号部分,很多比较重要的应用程序都需处理信号.第 9 章需要先了解信号机制再看,所以先跳过不讲.现在开始详解信号. 一.信号概念 信号是提供异步事件处理机制的软件中断. 这些异步事件可能来自硬 ...

  6. UNIX再学习 -- exit 和 wait 系列函数

    我们一开始讲进程环境时,就有提到了.进程有 8 种方式使进程终止. 其中 5 种为正常终止,它们是: (1)在 main 函数中执行 return (2)调用 exit 函数,并不处理文件描述符,多进 ...

  7. UNIX再学习 -- 系统数据文件和信息

    UNIX 系统的正常运作需要使用大量与系统有关的数据文件,例如,口令文件 /etc/passwd 和组文件 /ect/group 就是经常被多个程序频繁使用的两个文件.用户每次登陆 UNIX 系统,以 ...

  8. UNIX再学习 -- 文件和目录

    文件I/O部分断断续续写了三天,最后总结发现还有好多内容是略过没讲的,我的内心是崩溃的.UNIX环境高级编程这本书,虽然我只看了四章我就发现了书里面的内容讲的太跳,如果是刚接触UNIX或者没有一点C语 ...

  9. UNIX再学习 -- shell编程

    UNIX环境高级编程看了三章,遇到不少重定向等shell命令.本想到Linux时再讲,看来有必要提前了.之前有看过一本<嵌入式Linux软硬件开发详解>这本书里有简单介绍了一部分shell ...

最新文章

  1. 谈谈Linux下的数据流重定向和管道命令
  2. 打印折痕方向(二叉树应用)
  3. 数据结构中缀表达式转后缀表达式与后缀表达式的求值实训报告_动图+源码,演示 Java 中常用数据结构执行过程及原理...
  4. 复制出来的文本都是大写_vi或vim怎么复制粘贴
  5. Redis的编译安装
  6. 计算机故障检修课过时,第三场公开课|电脑故障维修以及笔记本知识科普
  7. graphics | R语言的基础绘图系统(二)—— 绘图参数及par函数
  8. @程序员,如何用最少的字节编写 C64 可执行文件?
  9. 整理收藏-mysqldump导出数据库
  10. 中琛物联‘连接+云+数据’服务助阵
  11. 23种设计模式(八)对象创建之抽象工厂
  12. Instgram和color,谁会更成功?
  13. PASCAL-VOC2012数据集介绍
  14. MATLAB-数据插值
  15. 苹果服务器文件夹共享权限设置,苹果设备如何访问 Windows 文件共享?
  16. Express框架、Webstorm中创建Express项目
  17. 各种浏览器下载tampermonkey网址
  18. 中国医师节丨华为IdeaHub用远程诊疗护佑人民健康,为医生减负
  19. 【Echarts】设置主题、扇形格式化
  20. 华为p30怎么升级鸿蒙系统

热门文章

  1. php 将查询出的数组数据存入redis
  2. RedHat/CentOS发行版本号及内核版本号对照表
  3. [leetcode] Restore IP Addresses
  4. hdu 1757 矩阵连乘
  5. Win10:tensorflow 学习笔记(1)
  6. 优先队列(priority_queue)的原理及用法
  7. copyof java_死磕 java集合之CopyOnWriteArrayList源码分析
  8. Gcc编译链接及常用选项总结
  9. 一场惊心动魄的国际黑客入侵保卫战
  10. [scala-spark]7. list 与 map