linux程序设计——linux环境(第四章)

4.5    用户信息

这篇为linux环境,代码在linux环境代码下载。除了著名的init程序以外,所有的linux程序都是由其他程序或用户启动的。(内核自行启动(已经被载入内存,开始运行,并已初始化所有的设备驱动程序和数据结构等)之后,就通过启动一个用户级程序init的方式,完成引导进程。所以init始终是第一个进程(其进程编号始终为1)。
当一个用户登录进linux系统时,用户有一个用户名和密码,一旦用户名和密码通过验证,用户就可以进入一个shell。从内部机制来说,用户还有一个唯一的用户标识符UID,linux运行的每个程序实际上都是以某个用户的名义在运行,因此都有一个关联的UID。
可以对程序进行设置,让它们的运行看上去好像是由另一个用户启动的,当一个程序的SUID位被置位时,它的运行就好像是由该可执行文件的属主启动的。当su命令被执行时,程序的运行就好像是由超级用户启动的,它随后验证用户的访问权限,将UID改为目标账户的UID值并进行该账户的登录shell。
UID由它自己的类型-uid_t,通常是一个小整数。
#include <sys/types.h>
#include <unistd.h>
uid_t getuid(void);
char* getlogin(void);
getuid函数返回程序关联的UID,它通常是启动程序的用户的UID。
getlogin函数返回与当前用户关联的登录名。
系统文件/etc/passwd包含一个用户帐号数据库。它由行组成,每行对应一个用户,包括用户名、加密口令、用户标识符(UID)、组标识符(GID)、全名、家目录和默认shell。例如
liu:x:1000:1000:liu:/home/liu:/bin/bash
人们定义了一组函数提供一个标准而又有效的获取用户信息的编程接口:
#include <sys/type.h>
#include <pwd.h>
struct passwd *getpwuid(uid_t uid);
struct passwd *getpwnam(const char *name);
密码数据库结构passwd定义在头文件pwd.h中,它包含以下成员:
passwd成员                  说明
char* pw_name           用户登录名
uid_t pw_uid                 UID号
gid_t pw_gid                 GID号
char* pw_dir                 用户家目录
char* pw_gecos          用户全名
char* pw_shell            用户默认shell
getpwuid和getpwnam函数都返回一个指针,该指针指向与某个用户对应的passwd结构。这个用户通过getpwuid的UID参数或通过getpwnam的用户登录名参数来确定。出措时,它们都返回一个空指针。
编写user.c程序从密码数据库中提取出一些用户信息。

4.6    主机信息

正如程序可以查找用户信息一样,程序也可以获得运行它的计算机的有关细节。uname命令就提供这类信息。
主机信息在许多情况下都很有用,可能需要根据程序运行的机器在网络上的名字来定制程序的行为。
如果系统安装了网络组件,可以通过gethostname函数获取它的网络名:
#include <unistd.h>
int gethostname(char* name, size_t namelen);
gethostname函数把机器的网络名写入name字符串,该字符串至少由namelen个字符长。成功时,返回0,否则返回-1。
可以通过uname系统调用获得关于主机的更多详细信息:
#include <sys/utsname.h>
int uname(struct ustname* name);
uname函数把主机信息写入name参数指向的结构。
编写程序hostget.c提出一些主机信息

4.7    日志

许多应用程序需要记录它们的活动,系统程序经常需要向控制台或者日志文件写消息。这些消息可能指示错误、警告或者与系统状态有关的一般信息。
通常这些日志信息被记录在系统文件中,而这些系统文件被保存在专用于此目的的目录中,可能是/usr/adm或者/var/log目录。
虽然系统消息的格式和存储方式不尽相同,但产生消息的方式却是标准的。UNIX规范通过syslog函数为所有程序产生日志信息提供了一个接口:
#include <syslog.h>
void syslog(int priority, const char *message, arguments...);
syslog函数向系统的日志设施发送一条日志信息。每条消息都有一个priority参数,该参数是一个严重级别与一个设施值的按位或。
编写程序syslog.c
可以使用setlongmask函数来设置一个日志掩码,通过它来控制日志信息的优先级。优先级在日志掩码中置位的后续syslog调用都将被丢弃。
编写程序logmask.c
logmask.c还用到了getpid函数,它和getppid的定义如下:
#include <sys/types.h>
#include <unistd.h>
pid_t getpid(void);
pid_t getppid(void);
两个函数分别返回调用进程和调用进程的父进程的进程标识符PID

4.8    资源和限制

linux系统上运行的程序会受到资源限制的影响。它们可能是硬件方面的物理性限制(例如内存)、系统策略的限制(例如允许使用的CPU时间)或者具体实现的限制(例如整数的长度或文件名中所允许的的最大字符数)。
头文件sys/resource.h提供了资源操作方面的定义,其中包括程序长度、执行优先级和文件资源等方面限制进行查询和设置的函数:
#include <sys/resource.h>
int getpriority(int which, id_t who);
int setpriority(int which, id_t who, int priority);
int getrlimit(int resource, struct rlimit *r_limit);
int setrlimit(int resource, const struct rlimit *r_limit);
int getrusage(int who, struct rusage* r_usage);
id_t是一个整数类型,它用于用户和组标识符,在头文件sys/resource.h中定义的rusage结构用来确定当前程序已耗费了多少CPU时间,它至少包含了两个成员:
rusage成员                             说明
struct timeval ru_utime        使用的用户时间
struct timeval ru_stime        使用的系统时间
一个程序耗费的CPU时间可分为用户时间(程序执行自身的指定所耗费的时间)和系统时间(操作系统为程序执行所耗费的时间,即执行输入输出操作的系统调用或其他系统函数所花费的时间)。
每个运行的程序都有一个与之关联的优先级,优先级越高的程序将分配到更多的CPU可用时间。
普通用户只能降低其程序的优先级,而不能升高。
应用程序可以用getpriority和setpriority函数确定和更改它们的优先级。
被优先级函数检查或者更改的进程可以用进程标识符、组标识符或用户来确定。
which参数指定了对待who参数的方式
which参数                        说明
PRIO_PROCESS            who参数是进程标识符
PRIO_PGRP                    who参数是进程组
PRIO_USER                    who参数是用户标识符
因此,为确定当前进程的优先级,可以调用
proprity = getpriority(PRIO_PROCESS, getpid());
默认的优先级是0,正数优先级用于后台服务,它们只在没有其他更高优先级的任务准备运行时才执行。负数优先级使一个程序运行更频繁,获得更多的CPU可用时间。优先级的有效范围是-20~20.数值越高优先级越低。
编写程序limits.c

4.9    小结

在本章中,了解了linux环境,并对程序运行的条件进行了研究,学习了命令行参数和环境变量,它们都能用来改变程序的默认行为,并提供有用的程序选项
还介绍了程序怎样利用库函数来处理日期和时间值,获得自身、用户以及它运行之上的计算机的相关信息。
因为linux程序通常要共享主机上的宝贵资源,所以本身也对如何确定和管理资源的问题做了介绍。

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。