/***********************************************************************************/
UNIX环境高级编程
/***********************************************************************************/
1. UNIX基础
/etc/passwd :
ding:x:1001:1001:ding,,,:/home/ding:/bin/sh
shell: sh, csh, ksh
<unistd.h>--><sys/types.h>-->原始数据类型_t
errno : 出错时才检查它;无错,也不会被清除;最好保存一下,否則可能被其他进程修改
strerror(errno) or perror("what's err") 基于errno的错误信息
进程时间 VS 日历时间(UTC:1970,1.1.所经过的秒数)
$ time ls 、、 进程时间
real 0m0.002s 时钟时间,总量时间
user 0m0.000s 用户CPU时间,执行用户指令的时间
sys 0m0.000s 系统CPU时间,执行内核的时间,e.g. read()
系统调用 和 库函数
系统调用 是访问内核的入口,如 printf 将调用write
不带缓存的I/O vs 标准I/O
fork, exec vs system
4 文件和目录
stat, fstat, lstat(文件或链接) // struct stat
if(S_ISBLK(stat.st_mode)) // 文件类型:普通, 目录, 字符, 块, FIFO, 套接字, 符号链接
S_ISUID(stat.st_mode) //测试设置用户ID位: 当执行该文件时,将进程的有效用户ID 设置为 该文件的所有者st_uid
ding@ding-desktop:~$ ls /etc \
> /tmp
7 UNIX的进程环境
内核->exec->C启动例程->main
exit VS _exit and atexit // exit比_exit多执行atexit(如果有的话),fclose等清除操作
extern char ** environ; // 用于查看所有环境变量,其他的用getenv...
C程序存贮空间布局: 低地址--》代码 初始化数据 未初始化数据 堆 栈 命令参数--》高地址
brian@ubuntu:~$ size /bin/cp
text data bss dec hex filename
97994 824 1636 100454 18866 /bin/cp
malloc VS calloc VS realloc VS alloca
realloc 重新分配新的长度,有可能把原来的拷贝到新的大的区域,所以不要有指针指向它
calloc 分配N个对象,初始化为0
alloca 在栈上分配空间,自动释放,但有些系统不支持
setjmp VS longjmp // 深层套嵌的函数出错后,跳到外面来; main 中用setjmp设置返回的位置,里层用longjmp实现跳转
volatile int sum; 将变量加此修饰符(易失变量) 后,不管是否优化,其值为调用longjmp时的值。
9.用C来访问它
函数方式 getenv() setenv() unsetenv()
变量方式
#include <stdio.h>
extern char**environ;
int main ()
{
char**var;
for (var =environ;*var !=NULL;++var)
printf ("%s \n ",*var);
return 0;
}
例子
#include <unistd.h>
确定可配置的系统变量的值
num_procs = sysconf (_SC_NPROCESSORS_CONF);
printf ("CPU 个数为: %ld 个\n", num_procs);
#include<pwd.h>
#include<sys/types.h>
得到uid,以及密码
uid = getuid())
struct passwd * getpwuid(uid_t uid);
根据秒数格式化时间
char* p = "1329123424"
time_t time; // 1970.1.1 开始的秒数 , time_t 是长整型
time = atol(p) + timezone
strftime( tmpbuf, MESSAGE_LEN, "%m-%d-%Y %T", localtime(&time)); // localtime 通过秒数计算时间,返回由年,月,日等构成的结构体
重定向
freopen("debug\\in.txt","r",stdin); //输入重定向,输入数据将从in.txt文件中读取
freopen("debug\\out.txt","w",stdout); //输出重定向,输出数据将保存在out.txt文件中
freopen( "CON", "w", stdout ); //输出到控制台"CON"
/home/workspace_forEclipse/DLD_CLI/Debug/DLD_CLI < input.txt > ret.txt 2 > err.txt
Cannot get the attribution of the terminal: Inappropriate ioctl for device##
复制文件描述符 以及 流的重定向
fd = dup(1); // 把标准输出 复制一份 给新的文件描述符fd. fd 与 1 有相同的文件指针。
dup2(from, to) != to // 把 from dup 给 to. from, to都指向 from !
屏蔽别的模块的打印
#include <fcntl.h>
// 把标准输出重定向到空洞文件,即开始屏蔽打印
int saveFd = dup(1);
int newFd = open("/dev/null", O_RDWR);
//int newFd = open("/dev/tty", O_RDWR);
dup2(newFd, 1);
close(newFd);
...
// 恢复打印
dup2(saveFd, 1);
字串转化为长整形
char buffer[20]="10379cend$3";
char *stop;
printf("%d\n",strtol(buffer, &stop, 2)); //stop返回非法字符的首地址; 2为转换的2进制
printf("%s\n", stop);
输出结果:
2
379cend$3
16进制的40 数字 转换为 10进制串
char message[3];
sprintf(message, "%d", 40); //字串40
// 将字串40按照16进制来转化,得到10进制数字
long int prelen = strtol(message, NULL, 16);
sprintf(message, "%ld", prelen); // print str "64"
字串转double
strtod > Convert string to double
atoi > Convert string to int
atol > Convert string to long int
字串复制
t = strdup(s); // 函数内分配内存
free(t); // don't forget!
字串比较,忽略大小写
strcasecmp
在源字串中查找目的字串中任一字符,并返回第一个找时的地址。
result = strpbrk( string, "0123456789" );//在string中找出最先出现0~9中某一个字符的位置
字串中查找字符
tptr = strchrnul(urlp, ' '); // 未找到,返回串尾
script = strchr(script + 1, '/') // 未找到,返回NULL
char * p = strrchr(buf, ' '); // 反向搜索字符
小写字符变大写
0100 0001 65 41 A
0110 0001 97 61 a
ch = (buf[0] & ~0x20); /* toupper if it's a letter */
C 正则表达式函数
#include <regex.h>
regcomp(结构体指针, 正则表达式,标志);
regexec(编译好的结构体, 待查找的字串,找到的个数,找到的结构体数组,标志);
打印N个相同的字符,且字符数字为变量
fprintf(stderr, "%*c ^\n", iLen, ' ');
取字串
sscanf(data,"username=%[^&]&password=%[^&]",username,password);