Unix

来源:互联网 发布:万能弹簧机的编程 编辑:程序博客网 时间:2024/05/19 00:54

Unix

sf2gis@163.com

2014年5月15日

 

1  概述

1.1 计算机操作系统组成

0层:OS核心:较小,各种硬件的驱动。

1层:系统调用:OS核心所提供的接口,可以提供硬件服务(标准C提供同名函数)。是最小的系统接口。

2层:

shell:命令行解释器。提供各种系统调用之上的便捷服务。多用于交互(以$开头)。

公用函数库:二进制函数库。提供各种系统调用之上的通用服务。基于系统调用的二次开发,提供许多简便函数,多用于编程。

3层:应用程序:综合使用1层、2层及本层其它程序,完成各种业务逻辑的软件。

1.1.1shell

shell是用户与系统调用的交互程序,可以有多种版本存在。LINUX下通用的是bash。

linux查看系统中安装的sh版本:

cat /etc/shells

查看当前版本:

echo $SHELL

linux修改默认shell的方法(重启后生效):

chsh s /bin/sh

参考

http://blog.sina.com.cn/s/blog_6c9bac050100wg9s.html

 

1.2 文件系统

/:根目录。

/etc:不是单词缩写,表示等等的意思。保存系统和应用程序的全局配置等文件。

/etc/passwd:保存所有用户的用户名和密码。

用户名:x(加密密码):用户ID:组ID:注释:起始目录(home directory):shell版本

用户ID:由系统管理员指定。root为根用户,ID=0。

组ID:不同用户的分类ID。在/etc/group文件中保存。

文件名:不能包含/和null。/用于区分路径,null用于标识结束。

路径:/开头的为绝对路径;无/的为相对路径,从当前路径开始。

文件描述符:文件表示系统可以使用一种的IO设备。所有系统使用的文件都被分配一个系统索引值(文件描述符)为标识。cin(0),cout(1),cerr(2):标准文件描述符。CTRL+D:表示EOF。

系统调用:#incude<dirent.h>:与目录相关的API。

#include<unistd.h>: posix系统调用接口(与windows.h相对应)。

参见:http://baike.baidu.com/view/2262790.htm

 

1.3 程序、进程和线程

程序是存在存储设备上可被系统执行的文件。

进程是系统将程序读入内存,并执行的程序实例。

进程ID:系统分配给每个进程的索引值(非负)。

1.3.1进程控制函数:exec、fork、waitpid。

fork():创建子进程(父进程的复本)。返回值:负值:表示出错;0:表示子进程返回;正值:表示子进程pid。fork()被父进程调用一次,产生子进程;返回两次,子进程返回0并结束,父进程返回pid。

exec():执行指定的程序。

waitpid():等待指定的进程结束。

通常使用fork()创建子进程,然后用exec()执行程序,使用waitpid()监视子进程。

1.3.2线程  

线程是后来多核CPU出现后才出现的概念,表示同一个进程中不同的处理单元。由进程管理,每个线程分配一个索引ID(只在进程中有效)。

1.3.3错误码

任何程序都不会将错误码置0。

如果没有出错,则不对错误码进行任何处理。

各个线程都有独立的错误码。

1.4 用户和组

root的用户id=0。

Ubuntu默认使用user登录,不可以直接使用root。默认root密码是动态变化的。如果要启用root,则在user下,使用sudosu,进入root。从root切换为user,则使用su user

设定root的固定密码:sudo passwdroot,然后根据提示设定。

禁用root:sudo passwd –l root;(只是设定root的密码过期,仍然使用sudo su进入)

启用root:sudo passwd –u root;(设定密码不过期)

参考:http://www.cnblogs.com/weiweiqiao99/archive/2010/11/10/1873761.html

getuid(),getgid():返回用户id和组id。

1.5 信号

当系统需要通知进程某些消息时,使用信号SIG。进程接收到信号后要吧进行三种处理:忽略、默认处理、自定义处理(使用signal(SIG,函数)指定)。

进程发出的中断信息。

CTRL+C:中断。SIGINT。

CTRL+\:中止。或kill()函数。

 

1.6 时间

time_t:日历时间,1970-1-100:00:00以来累积的秒数。系统调用仅提供本类型。

clock_t:进程时间。包含real(历时)、user(用户使用CPU时间)、sys(系统调用进程使用CPU时间)。

1.7 限制

<limits.h>设置了当前环境的各种限制。

<sys/types.h>:设置了与实现有关的基本类型。

2 IO

使用文件描述符操作。不带缓冲区的系统调用。

#include<fcntl.h>

<unistd.h>中定义STDIN_FILENO(0),STDOUT_FILENO(1),STDERR_FILENO(2)来定义标准文件描述符。OPENMAX表示文件描述符的最大值(早期是10,后来是63,现在多取决于硬件)。

/dev/fd:保存文件描述符。

2.1 操作函数

2.1.1int open(path,flag,mode)

打开指定路径的文件,并指定打开模式。成功则返回文件描述符,失败,则返回-1。

flag:O_RDONLY,O_WRONLY,O_RDWR。必选,只能选一个。

O_APPEND,O_CREATE,O_EXCL,O_TRUNC,O_NOCTTY,O_NONBLOCK。可选。

mode:指定访问权限(创建时使用)。

2.1.2int create(path,flag,mode);

创建文件。与open(path,O_WRONLY|O_CREATE|O_TRUNC,mode)相同。

2.1.3int close(fileindex);

#include<unistd.h>中定义。

关闭文件及其中的锁。进程终止时,自动关闭所有文件及其锁。

2.1.4off_tlseek(fileindex,offset,SEEK_SET(0)/SEEK_CUR(1)/SEEK_END(2));

成功返回当前偏移量(有可能是负值),失败返回-1。

当前偏移量为:lseek(fileindex,0,SEEK_CUR);

2.1.5ssize_t read(fileindex,char*buf,size_t count);

读取文件,从当前位置开始的count个,存入buf。成功返回读取个数,到达文件结尾返回0,失败返回-1。

ssize_t write(fileindex,const char *buf,size_tcount);

写入文件,从当前位置开始的count个(从buf中读取)。成功返回读取个数,失败返回-1。

如果打开文件时指定了O_APPEND标志,则每次写入之前都会将位置指定为结尾,并在成功写入后将当前位置增加相应数目。

dup(filedes):复制文件描述符。

dup2(filedes,filedesDestination):复制文件描述符为指定值。

int access(path,mode):测试权限与存在性。

truncate/ftruncate:截断。

2.2 状态函数

stat:文件信息。

fstat:文件描述符指向的文件信息。

lstat:文件和链接信息。

chmod/fchmod:更改权限。

chown/fchown/lfchown:更改所有者。

2.3 系统文件打开管理

系统使用表管理打开的文件,内核创建一张文件表,包含文件打开标志,当前位置,inode指针。

每个打开的文件都由一个信息节点(i-node),包含文件的基本信息。

进程中同样维护一个文件描述符表,代表当前进程中打开的文件,包含标志和内核文件表项指针。

2.4 文件系统

硬盘可以分为多个分区。每个分区由一个文件系统组成。

文件系统由多个块组成。第一块称为超级块,包含文件系统的信息。其它块组成不同的柱面组。每个柱面组包含i节点和数据块。i节点包含数据块的指针和相应信息。目录块是包含文件索引(文件名称和i节点)的特殊块。

每个文件都有i节点,包含文件的信息(也包含硬连接记数)。

内核维护一张文件描述符表,其表项为:文件状态、当前偏移量、i节点指针。

进程的进程表中有打开文件记录项,其为一张打开文件的文件描述符表,其表项为:标志、内核文件描述符表项指针。

由于多进程可能同时写入同个文件,有可能导致错误。使用open的O_APPEND使每次写入都将定位于最后位置。O_CREAT|O_EXCL:保证在创建和打开之前不会被其它进程创建。

dup(filedes):复制当前文件描述符到新文件描述符。

dup(filedes1,filedes2):复制当前文件描述符到指定的文件描述符。

fcntl(filedes1,flag,filedes2):操作文件描述符。

flag:F_DUPFD,F_SETFD/F_GETFD,F_SETFL/F_GETFL,F_SETOWN/F_GETOWN,F_SETLK/F_GETLK/F_SETLKW);

F_GETFL的O_RDONLY/O_WRONLY/O_RDWR只占一个标志,与O_ACCMODE进行&操作来获取。

ioctl():<sys/ioctl.h>高级io操作。

/dev/fd/n:表示文件描述符,打开操作与dup操作相同。

2.4.1硬连接、符号连接

硬连接:是指目录块中一个项,指向文件i节点。

符号连接:是指一种文件类型,其中内容为一个指向硬连接的指针。

只有指向i节点的硬连接数为0,且没有被打开的情况下,才会删除。

为防止程序崩溃时创建的临时文件没有删除,通常在打开文件后,马上使用unlink,只要程序关闭(正常、非正常),都会删除文件。

目录不能创建硬连接,因为有可能出现死循环。

删除目录使用rmdir。

<unistd.h>

link(oldpath,newpath)

unlink(path)

symlink(actpath,sympathy);

readlink(path,buf,size);

<stdio.h>

remove(path);可以删除目录和文件。

rename(oldname,newname);

2.4.2目录操作

#include<unistd.h>

mkdir(path,mode);

rmdir(path);

#include<dirent.h>

DIR *opendir(path);

struct dirent*readdir(DIR);

rewinddir(DIR);回到开头。

closedir(DIR);

char *getcwd(buf,size);

int chdir(path);

int fchdir(path);

2.5 IO缓冲管理

#include<unistd>

void sync(void):缓冲区更新内容加入写入队列(马上返回,不等待实际写入)。

int fsync(filedes):指定文件缓冲区更新(数据+属性),等待实际写入结束。

int fdatasync(filedes):指定文件缓冲区更新(只有数据),等待实际写入结束。

2.6 文件状态管理

#include<fcntl.h>

int fcntl(filedes,int cmd,int arg):管理文件的各种状态。

2.7 文件类型

2.7.1普通文件

二进制文件或文本文件等文件,只需要其处理程序能够识别就可以。

二进制可执行文件,要求能够被内核识别。

2.7.2目录文件

包含其包文件的名称与指针。只有内核能够直接管理,其它程序需调用内核。

2.7.3块特殊文件(有缓冲),字符特殊文件(无缓冲)

设备IO只能以这种文件存在。

2.7.4FIFO:用于进程间通信(命名管道)。

2.7.5socket

用于进程间网络通信(也可以进行本地进程间通信)。

2.7.6symbolic link:符号链接(快捷方式)。

2.8 文件属性

<sys/stat.h>

S_ISREG、S_ISDIR、S_ISFIFO、S_ISBLK、S_ISCHR、S_ISLNK、S_ISSOCK

IPC对象:S_TYPEISSEM、S_TYPEISSHM、S_TYPEISMQ(POSIX中定义为文件,实际系统未实现)。

int stat(pathname,pStat);

int fstat(filedes,pStat);

int lstat(pathname,pSata);

stat结构信息:

st_size:文件长度。

st_blksize:单位块字节数。

st_blocks:块数。

st_mode:文件类型。

st_uid,st_gid:uid,gid。

st_dev,st_rdev(字符和块设备,包含实现的设备号):设备号。

2.8.1以当前用户id测试文件访问属性

<unistd.h>

access(path,mode);R_OK/W_OK/X_OK/F_OK

2.8.2文件访问性掩码

<sys/stat.h>

mode_t umask(mode);设置文件在当前用户下的默认禁止使用访问标志。

2.8.3修改文件访问属性

<sys/stat.h>

chmod(path,mode)

fchmod(filedes,mode)

2.8.4修改文件访问属性S_ISVTX

最初用于缓存程序,当前用于保存设置删除权限:只有具有写权限的本人、本人的目录、root权限时才可以删除。

2.8.5修改文件所有者、所有组属性

<unistd.h>

chown(path,uid,gid);

fchown(filedes,uid,gid);

lchown(path,uid,gid);

需要root权限。

2.8.6截短文件

<unistd.h>

truncate(path,lenght)

ftruncate(filedes,length);

2.8.7文件时间

系统保存文件的最后访问时间(st_atime),文件内容的最后修改时间(st_mtime),i节点的最后修改时间(st_ctime)。系统不保存i节点的最后访问时间。

st_atime,st_mtime可以用utime更新时间(使用NULL,则设置为当前时间)。

st_ctime无法直接更新,只能使用utime更新时,自动更新。

#include<utime.h>

int utime(path,utimbuf);

struct utimbuf

{

    time_tactime;

    time_tmodtime;

}

3 进程

C程序内存布局

高地址      环境变量

|                           栈

|                           内部地址空间       

|                           堆

|                           BSS:未初始化变量(block started by symbol)

|                           初始化变量

低地址      程序正文(可共享)

3.1 进程ID

系统使用进程ID管理进程。进程ID可以复用,但会延迟复用。

ID=0的进程是系统调度进程,内核进程。

ID=1的进程是系统初始化进程,用于配置当前系统,用户进程,始终运行。/sbin/init。

ID=2的进程是页守护进程,用于管理虚拟存储的分页操作。

#include<unistd.h>

getpid,getppid,getuid,geteuid,getgid,getegid

3.2 进程创建

fork():创建子进程,复制父进程的地址空间和堆、栈(现在的实现方式为COW-copy on write)。子进程返回0,父进程返回子进程的pid,调用一次,返回两次。无法确定父子进程的运行顺序。

vfork():创建子进程,在调用exec/exit之前在父进程中运行(如果没有发现这两个函数,则重复执行自身),不进行复制。保证子进程先运行,然后再运行父进程。其它与fork相同。

execl/v[+e/p]:使用一个指定的程序替换当前的进程。l:以(char*)NULL结束的字符串序列。v:字符串数组,e:可以传递环境变量,p传递文件名。execve:是系统调用,其它是库。

3.3 等待子进程

#include<sys/wait.h>

wait()、waitpid()

3.4 进程结束

5种正常结束方式:

1)   main中返回。(默认调用exit)

2)   exit:执行atexit设定的函数,关闭相关资源(但不处理文件描述符)。

3)   _exit/_Exit:exit中除执行atexit设定的函数外,其它操作在本函数执行。由exit调用。

4)   进程的最后一个线程返回。进程返回0。

5)   进程的最后一个线程调用pthread_exit。进程返回0。

3种异常结束方式:

1)   调用abort

2)   响应取消

3)   响应信号

如果子进程已经结束,但父进程并未处理,则称之为僵尸进程。

如果子进程结束之前,父进程已经结束,则将父进程指定为init进程。

3.5 更改用户

#include<unistd.h>

setuid(),seteuid(),setreuid(),setgid(),setegid(),setregid()

3.6 解释器文件

#! pathname [arguments]

cmd

使用execl执行解释器文件时,注意要使用绝对路径。

3.7 system

#include<stdlib.h>

intsystem(pCmd);

如果pCmd是NULL,测试可用性,如果返回非0,则可用。

3.8 loginusername

#include<unistd.h>

char *getlogin(void);

3.9 time

#include<sys/times.h>

clock_t times(struct tms *buf);

4 线程

#include <pthread.h>

编译时添加 –l pthread链接静态库。

参考:http://blog.csdn.net/llqkk/article/details/2854558

 

bool pthread_equal(pthread_t t1,pthread_t t2);

比较两个线程id(可能由结构实现),相同则返回非0,不相同返回0。

pthread_t pthread_self(void);

返回当前线程的id。

int pthread_create(pthread_t *restrict pTid,const pthread_attr *restrict pAttr,void *(*thread_fun)(void*),void*arg);

创建线程。

void pthread_exit(void *);

退出线程。

int pthread_join(threadid,void **);

获取threadid的返回值。

int pthread_cancel(threadid);

取消其它线程。

void pthread_cleanup_push(void (*fun)(void *),void*arg);

void pthread_cleanup_pop(int0;

清理函数要成对出现。

线程同步

mutex:互斥量,只有加锁和解锁两种状态。

读写锁:有读锁、写锁、解锁三种状态。

条件变量:互斥量升级版,可以设置超时。

pthread_mutex_init/pthread_mutex_destroy;

pthread_mutex_lock/pthread_mutex_trylock/pthread_mutex_unlock;

pthread_rwlock_init/pthread_rwlock_destory;

pthread_rwlock_rdlock/pthread_wrlock/pthread_unlock;

pthread_cond_init/pthread_cond_destory;

pthread_cond_wait/pthread_cond_timedwait;

0 0
原创粉丝点击