系统编程.docx

上传人:b****9 文档编号:23390652 上传时间:2023-05-16 格式:DOCX 页数:55 大小:101.60KB
下载 相关 举报
系统编程.docx_第1页
第1页 / 共55页
系统编程.docx_第2页
第2页 / 共55页
系统编程.docx_第3页
第3页 / 共55页
系统编程.docx_第4页
第4页 / 共55页
系统编程.docx_第5页
第5页 / 共55页
点击查看更多>>
下载资源
资源描述

系统编程.docx

《系统编程.docx》由会员分享,可在线阅读,更多相关《系统编程.docx(55页珍藏版)》请在冰豆网上搜索。

系统编程.docx

系统编程

第1章:

系统开发基本概念

1.操作系统基本构成

内核3大作用:

管理硬件(内核里面许多附加驱动程序);管理内存(分页管理,换入换出);管理进程(控制进程声明周期)

管理系统工具、应用程序和硬件的交互,和硬件的操作必须通过内核。

(内核提供系统调用)

管理交换空间、文件系统、精灵程序;

系统调用:

内核给用户提供的一组函数,用户通过它们可以直接操作内核实现具体功能。

库函数:

例如stdio.h里面输入输出库函数,完全是基于系统调用实现。

Shell:

本质上也是通过系统调用实现。

用户应用程序:

可以借助以上三者(本质借助系统调用)实现和内核的交互。

2.Linux系统基本概念

文件(系统上数据/etc/passwd|设备/dev/sda1的组织方式)

文件系统:

管理文件的一个数据结构、逻辑组织

程序(可运行代码,静态)

进程(程序运行实例|整个过程,动态)

线程:

轻量级进程,只需要很小的资源,就可以维持运行,进程需要大量资源。

信号:

进程间通信技术之一。

$kill-9uid

客户机服务器:

由资源提供消耗而定,与网络无关

3.linux系统启动流程

第一阶段:

bootlooder

1)硬件自检,初始化芯片CPU

2)初始化少量外围设备

3)启动选择器(双系统),加载操作系统内核

第二阶段:

linux内核启动阶段

1)挂载initrd文件,形成最小根文件系统;(/boot/initrd*)

2)以最小文件系统为依托,导入整个文件系统,执行/sbin/init文件,实现系统的启动

0号进程:

内核进程

ps-ef|grep/sbin/init==>1号进程

第三阶段:

用户进程启动阶段

由1号进程启动多个子进程,支持系统启动

1)exec/etc/init.d/*执行相关文件(shell脚本),启动相应程序,实现系统配置

2)exec/sbin/getty初始化标准输入、输出、错误设备

exec/bin/login产生用户登录界面

3)1号进程管理孤儿进程(父进程死掉的子进程)

4.linux内存布局

系统启动以后,对于32位平台,4G内存分为两部分,用户空间3G(0x00000000-0xC00000000),内核空间1G(0xC0000000-0xFFFFFFFF);

进程操作的数据、使用的资源属于用户空间,执行用户空间的代码,我们称之为进程处于用户态。

内核态:

进程在某些时间点操作内核数据或资源或运行内核代码。

通过系统调用实现。

5.系统调用

全部都是系统提供的C语言函数。

系统调用标准,一个四个:

ISOC(C语言标准,由C语言实现)

IEEEPOSIX(系统调用的构成,规定函数[名字、参数含义、返回值含义,出错标识]相关标准,最小系统调用标准)

SignleUNIXSpecification(用于扩展【建议性】的系统调用标准)

FIPS(基本淘汰,联邦信息处理标准,美国政府制定)

UNIX支持POSIX标准,windows逐步向该标准靠拢

第2章:

文件I/O

1.文件描述符

FILE结构体:

流如何关联到指定文件?

fopen();

typedefstruct

{

int-fd;//文件号文件描述符

int-cleft;//缓冲区中剩下的字符

int-mode;//文件操作模式

chsr*nextc;//下一个字符位置

char*buff;//文件缓冲区位置

}FILE;

进程如果要操作指定文件,必须通过内核,建立3个数据结构(文件描述符表FDT、文件表项、I节点),一级一级关联到文件。

文件表项FI:

文件状态信息(操作状态,偏移量、文件指针计数器等)

I节点:

文件属性信息(一般稳定,不轻易变化),类型、长度...(V节点属于UNIX)

包含文件描述符表的头文件:

/usr/src/linux-headers-3.2.0-23/include/linux/sched.h

structtask_struct{};存放进程相关信息的结构体

structfiles_struct*files;//文件描述符表,长度1024

2.文件I/O系统调用

openreadwritelseek(调整偏移量)close五个函数

练习:

实现cp命令,src/m_cp.c

size_t:

32位平台,typedefunsignedintsize_t;

ssize_t:

typedefsignedintssize_t;

creat()函数,早期版本,不推荐使用。

off_tlseek(intfd,off_toffset,intwhence);

off_t:

带符号的长整形数signedlongint

返回值是绝对偏移量(相对文件头)。

练习1:

通过lseek函数,计算文件长度,计算当前文件当前偏移量值。

src/lseek.c修改src/m_cp.c,每次读写,打印偏移量

练习2:

空洞(二进制0)文件的制作:

lseek(fd,10L,SEEK_END);//OK

lseek(fd,-10L,SEEK_SET);//ERROR

src/hole_file.c

$od-cfile.txt查看文件内容(字符形式)

3.I/O效率

读写数据时,发生中断次数越少,CPU效率更高。

一个磁盘块4096字节,即4KB时,效率最高,硬件相关。

4.文件共享

不同进程同时打开同一个文件,文件描述符表、文件表项、I节点的使用情况。

I节点共享,其他各自对立。

思考,两个进程同时操作同一文件追加数据,是否会遇到问题?

练习:

模拟上述情况的发生。

src/f_append1.csrc/f_append2.c

如何解决该问题?

让一个进程操作文件时,不允许别的进程做类似的操作。

即把操作调整成为原子操作。

5.原子操作--文件追加

打开文件时O_APPEND标记,操作文件时,保存文件长度、调整偏移量、修改文件长度三件事情成为一个原子操作,密不可分。

设置该标志后,调整偏移量不可用。

原子操作--文件中间部分插入

pread函数

pwrite函数

原子操作--文件创建

判断文件是否存在,创建文件,两件事是一个原子操作,即可避免问题。

open(“a.txt”,O_WRONLY|O_CREAT|O_EXCL,0777);

作业:

完整cat命令的使用:

Catcopy(STDIN_FILENO,STDOUT_FILENO);

cata.txtb.txtc.txtcopy(fd,STDOUT_FILENO)

cat都是元字符,属于shell提供的;

cat>p.txt

catp.txt

扩展:

cat命令用+替换<;用-替换>;

思考如何实现?

第二天授课:

6.文件描述符操作

Intdup(intfd);返回新的文件描述符(从FDT选最小的minfd),返回的minfd(和fd公用同一个文件指针)也

Intdup2(intfd1,intfd2);断开fd2与原来文件的关联(closefd2),将其关联到fd1文件描述符上。

(将fd1拷贝到fd2上,返回fd2成功),以上两个操作时原子操作。

练习:

使用dup2函数实现cat+(<)a.txt-(>)b.txt

src/my_cat.c

作业1:

完善src/my_cat.c

7.fcntl函数,修改文件结构信息

Intfcntl(intfd,intcmd,...);

第二个参数cmd,决定了函数的实际功能(共5种)。

1)fcntl(3,F_DUPFD);==dup(3);复制描述符,返回新描述符

close(5);fcntl(3,F_DUPFD,5);==dup2(3,5);把3复制到5,返回5。

2种区别:

dup2()是原子操作;出错errno;

2)修改FDT中fd的值,暂时不关注(第四章);

3)获得,修改文件状态标志(FI);

intval=fcntl(3,F_GETFL);返回值即可获得

fcntl(3,F_SETGL,val2);修改(val2覆盖)(val|var2追加)

去除val&=~var2;fcntl(3,F_SETFL,val)

注意:

其中O_RDONLYO_WRONLYO_RDWR并非各占1位,他们分别对应值0,1,2,且他们互斥。

如果判断,则(val&O_ACCMODE)==O_RDWRONLY。

练习:

获取一个文件描述符的读写权限。

src/read_or_write.c

练习:

实现追加、去除、修改文件状态标志模块函数。

include/io.h

打开一个文件,写入数据,添加O_APPEND标记,调整偏移量到头部,继续写入数据,验证是否添加标记成功!

Src/add_flag.c

8.ioctl函数I/O其他操作

主要针对设备文件,进行其他相关操作。

intioctl(intfd,intrequest,...);

后面两个参数,往往根据不同的驱动接口进行设置。

9.高级IO技术

1)阻塞IO模型,之前做的所有操作全部都属于阻塞模型,(主要针对于低速设备)

2)非阻塞IO模型,如果可以读写,就成功;不能读写,就返回错误信息,做别的事情

3)I/O多路转换,介于以上两者之间

4)信号驱动IO模型,信号章节讲解

5)异步IO模型,淘汰技术

练习:

非阻塞模式处理低速外围设备(键盘、屏幕)的输入和输出;

src/nonblock_read.c

src/nonblock_write.c/etc/ld.so.cache文件很大,读取数据然后输出到屏幕上,设置标准输出为非阻塞模式,看效果。

./a.outa.txt出错信息,调试信息输出到a.txt里面,方便观察

第三天授课

10.I/O多路转换

intselect(intnumfds,fd_set*readfds,fd_set*writefds,

fd_set*exceptfds,structtimeval*timeout);

fd_set:

若干个描述符构成的集合,是long类型的数组,共占128字节(1024位).exceptfds:

出现异常的

select系统调用,让内核观察一组文件描述符,返回准备就绪的描述符个数;如果出错返回-1;如果超时返回0;

structtimeval{//观察的时间

longtv_sec;//second秒

longty_usec;//usecod微秒

};

练习:

将0号描述符加入到文件描述符集中,设置内核观测,如果0号可用,操作,否则继续观测。

src/select_test.c

11.文件锁(记录锁)

多进程同时操作一个文件,如何实现数据操作,不至于出现紊乱。

记录锁分类:

共享读锁独占写锁

如何上锁:

fcntl函数实现

intfcntl(intfd,intcmd,...structflock*flockptr);

cmd:

F_SETLKF_SETLKW(wait阻塞)F_GETLK设置、获取锁

structflock{

shortl_type;//锁类型F_RDLCKF_WRLCKF_UNLCK

off_tl_start;//偏移量offset

shortl_whence;//相对位置SEEK_SETSEEK_CURSEEK_END

off_tl_len;//锁长度0表示整个文件

pid_tl_pid;//进程号(上锁时不需要,查询时使用)

};

include/io.hsrc/io.c

intlock_reg(fd,cmd,type,start,offset,len);

#defineREAD_LOCK[W](fd,start,offset,len)lock_reg(...)

练习:

两个进程同时对同一个文件一个字节一个字节写入数据,对文件上锁以实现数据安全。

src/append_file.c

注意:

文件锁分为建议性锁和强制性锁两类,默认全部是建议性锁。

Linux下命令设置强制性锁,$mount-Oomand/dev/sda3/opt

作业:

两个进程同时对同一文件(锁全部)读取数据,能否同时向下执行。

src/read_file.c

两个进程一个读取一个写入数据,验证能否同时执行。

src/read_write_file.c

扩展:

使用基本系统调用开发C语言标准库。

FILE*fp=fopen(“sss.txt”,”r”);

fflush(fp);

fclose(fp);

intc=fgetc(fp);

fwrite(buff,size,num,fp);

fread(buff,size,num,fp);

12.存储映射

用户空间,存储映射区,存在于堆空间和栈空间之间;

内核空间,也有内存映射区;

void*mmap(void*addr,size_tlen,intprot,intflag,intfileds,off_toff);返回值是映射的首地址。

void*addr:

确定存储映射的首地址,一般0,由系统提供

size_tlen:

映射长度

intprot:

映射模式PROT_READPROT_WRITEPROT_EXECPROT_NONE

intflag:

映射类型(是否立即同步)MAP_FIXEDMAP_SHAREDMAP_PRIVATE

intfileds:

文件描述符,操作的文件

off_toff:

文件偏移量

注意:

映射时往往不按照用户指定的len值映射,一般都会多。

不能对空白文件映射,没有任何意义。

解除映射

intmunmap(caddr_taddr,size_tsize);

练习:

映射一个文件到用户空间,然后读取,修改文件信息。

src/mmap_test.c

练习:

利用映射实现cp命令,src/mmap_cp.c

第4天:

(复习)

第2章文件和目录

1.stat结构体

用来描述文件属性信息;

1.struct stat  

2.{  

3.  

4.    dev_t       st_dev;     /*  -文件所在设备的ID*/  

5.  

6.    ino_t       st_ino;     /* inode number -inode节点号*/  

7.  

8.    mode_t      st_mode;    /* protection -保护模式?

*/  

9.  

10.    nlink_t     st_nlink;   /* -链向此文件的连接数(硬连接)*/  

11.  

12.    uid_t       st_uid;     /* user ID of owner -user id*/  

13.  

14.    gid_t       st_gid;     /* group ID of owner - group id*/  

15.  

16.    dev_t       st_rdev;    /* -设备号,针对设备文件*/  

17.  

18.    off_t       st_size;    /* total size, in bytes -文件大小,字节为单位*/  

19.  

20.    blksize_t   st_blksize; /* blocksize for ilesystem I/O -系统块的大小*/  

21.  

22.    blkcnt_t    st_blocks;  /* numberofblocks allocated -文件所占块数*/  

23.  

24.    time_t      st_atime;   /* time of last access -最近存取时间*/  

25.  

26.    time_t      st_mtime;   /* time of last modification -最近修改时间*/  

27.  

28.    time_t      st_ctime;   /* time of last status change - */  

29.  

30.}; 

 

intstat(constchar*pathname,structstat*buf);

intfstat(intfd,structstat*buf);

操作符号链接文件时,获得的是源文件的属性信息;

intlstat(constchar*pathname,structstat*buf);

可以用来获得符号文件本身的属性信息;

成功返回0,失败返回-1;

练习:

分别通过文件名、文件描述符获得文件属性信息,打印文件长度。

Src/lstat_test.c

char*ctime(time_tconst*time_value);将时间转换成能看懂的格式。

2.文件类型

七个宏用来判断七种文件类型:

普通文件(regularfile)S_ISREG()

目录文件(directoryfile)S_ISDIR()

块特殊文件(blockspecialfile)S_ISBLK()

字符特殊文件(chatacterspecialfile)S_ISCHR()

FIFO(namedpipe)S_ISFIFO()

套接字(socket)S_ISSOCK()

符号链接(symboliclink)S_ISLNK()

练习:

获得文件属性信息,判断其文件类型。

src/file_type.c

3.设置用户ID、组ID(所有进程都有角色)

实际用户ID(getuid()),实际组ID:

/bin/login实际登录的用户(谁启动了该进程,整个进程运行期间,不变)

有效用户ID(geteuid()),有效组ID:

(决定进程在访问文件时的权限问题)

多数情况下,实际ID和有效ID相同。

特殊情况下(进程对应的文件有设置位时,有效用户ID在进程执行过程中演变成由文件的拥有者决定)。

$passwd修改实际用户密码/usr/bin/passwd

$ls-l/usr/bin/passwd

$-rwsr-xr-x1rootroot412844月92012/usr/bin/passwd

在程序的执行过程中临时改变有效用户为root,通过保留用户ID、组ID实现。

4.文件权限

9中访问权限位:

S_IRUSR,S_IWUSR,S_IXUSR

S_IRGRP,S_IWGRP,S_IXGRP

S_IROTH,S_IWOTH,S_IXOTH

S_ISUID,S_ISGID设置用户ID和组ID。

练习:

获取文件权限,ls-l形式输出src/file_perm.c

作业:

实现简易版本的ls-l功能。

src/myls_l.c

5.access函数

用于验证实际用户能否访问指定文件

Intaccess(constchar*pathname,intmode);

成功返回0,失败返回-1;

Mode取值:

R_OK读权限W_OKX_OKF_OK:

是否存在

练习:

判断实际用户对指定文件的访问权限。

src/access.c

6.umask函数

创建屏蔽字(掩码):

创建文件时起作用。

创建文件:

0777-0111==06660110110110

&~umask(022)0111101101

0110100100==>644

创建目录:

0777&~(umask)==>

mode_tumask(mode_tmode);设置新的掩码,返回值是以前掩码

练习:

修改掩码,然后创建新文件src/umask.c

7.chmodfchmod函数

修改文件权限位

主要:

若要修改,满足条件:

进程有效ID(geteuid())==所有者ID实际ID:

getuid();

进程具有超级用户权限

练习:

修改指定文件权限位。

src/chmod_test.c

./a.out644a.txt

8.修改用户拥有者所属组

Intchown(char*pathname,uid_towner,gid_tgroup);

Intfchown(intfd,uid_towner,gid_tgroup);

//针对链接文件

Intlchown(char*pathname,uid_towner,gid_tgroup);

注意:

非超级用户不能修改用户拥有者uid。

非超级用户如果要修改gid,需要保证第二个参数的值为owner==-1|geteuid();

练习:

修改制定文件的uid和gid;src/chown_test.c

第5天:

9.文件截断(从尾部截,修改Inode中文件长度值)

inttruncate(char*pathname,off_tl);

Intftruncate(intfd,off_tl);

成功返回0,出错返回-1

练习:

修改制定文件长度;src/truncate_test.c

10.文件系统概念

索引块、数据块

硬链接:

指向同一个I节点(磁盘块,与内核Inode不同),指向同一个数据块;

软链接:

指向不同I节点,有自己对应的数据块;

$ls-li(I节点编号)a.txt

11.硬链接操作(操作目录数据块内容)

必须同一个分区;

不能对目录创建硬链接;

练习:

建立一个链接文件,然后删除源文件。

src/link_test.c

12.软链接操作

读取链接文件本身数据,返回读取字节数,失败返回-1;

ssize_treadlink(char*pathname,char*buff,size_tsize);

创建链接文件,成功返回0,失败返回-1;

Intsymlink(char*actualpath,char*sympath);

练习:

创建一个软链接文件,然后读取链接文件数据、链接到文件数据。

Src/readlink.c./a.outa.txta.ls

注意:

可以对不存在的文件创建软链接文件;

可以跨文件系统;

13.文件时间

st_atime:

文件数据(数据块)最后访问时间read(用户可以修改)

st_mtime:

文件数据(数据块)最后修改时间write(用户可以修改)

st_ctime:

I节点(文件属性)最后修改时间(用户无法操作)

思考:

如果对文件追加,以上三个数据都有哪些改变?

14.修改时间属性

intutime(char*pathname,structutimbuf*times);

成功返回0,失败返回-1;

structutimbuf{

time_t

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 初中教育 > 初中作文

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1