linux操作系统培训.ppt
Linux操作系统培训,内容摘要,Linux基础 Linux常用操作命令 Linux设备管理Linux文件管理Linux进程调度Linux多线程编程Linux进程间通信,Linux基础,操作系统的概念操作系统是管理计算机系统资源(软件和硬件)资源的系统软件,它为计算机提供方便,有效,安全,可靠的工作环境。主要包括:进程管理,存储器管理,设备管理,文件管理,作业管理等。操作系统的分类。操作系统分为实时操作系统和非实时操作系统,又可以分为嵌入式操作系统和非嵌入式操作系统等。linux操作系统即可以作为准实时的操作系统使用,也可作为非实时操作系统使用,并且可以满足服务器操作系统的要求,在桌面操作系统领域也得到较大的发展。所以,linux操作系统已经渗透到嵌入式领域、服务器领域、个人pc领域,成为目前应用领域最广的一种操作系统。,Linux基础,Linux系统的组成整个linux系统由内核、设备驱动、各种运行时的库、shell及应用程序等组成。Linux的启动过程。在硬件上电之后,首先会有一个自举程序运行(在嵌入式领域成为loader,在pc中成为bios),然后自举程序在初始化必要的硬件(例如内存)之后将linux内核读取到内存中,然后跳转到内核的开始位置运行linux内核.linux内核在进行必要的初始化设置工作和挂载根文件系统之后,会启动文件系统中的一个程序作为系统中的第一个进程,这个进程就是大名鼎鼎的init进程,init进程会,然后运行etc目录下的对应的shell脚本文件。,Linux基础,Linux内核的作用 内核是Linux操作系统的核心,它负责系统的文件管理、设备管理、进程管理、存储管理、网络协议,直接决定着系统的性能和稳定性。linux的版本号 通常我们所说的linux的版本号,指的就是linux内核的版本号。版本号由三部分组成主版本号、次版本号、末版本号。例如:2.6.19 2为主版本号、6为次版本号、19为末版本号。同时可以通过版本号来确定linux的版本是稳定版本还是开发版本(次版本号奇数为开发版本,偶数为稳定版本)。,Linux常用操作命令,Linux常用操作命令,Linux设备管理,Linux上层应用与实际设备的关联Linux对于设备的管理是通过设备驱动程序来进行管理,采用设备文件的方式进行关联。每个设备文件都有设备类型,主设备号、次设备号,在驱动程序中会注册这些设备号。这样当上层应用程序操作设备文件时,就会将请求通过Linux操作系统调用传递到驱动程序中,驱动程序控制硬件设备完成相应的操作。Linux设备文件一般在/dev目录下面。例如如下设备文件:crw-rw-1 root uucp 4,64 12月 8 09:57/dev/ttyS0是指/dev/ttyS0为字符型设备,主设备号为4,次设备号为64。其实这就是linux系统中的串口1的设备文件。我们打开这个设备文件,然后写入数据,我们写入的数据就会从串口发送出去,我们读入数据,就会读取到从串口收到的数据。如果我们想控制串口的速率、校验位、码位的长度,我们只需要调用ioctl函数,然后传入相应的数据就可以了。,Linux文件管理,Linux系统中使用的文件类型目前linux采用的文件系统有ext3文件系统,但是在嵌入式linux操作系统中更多的使用的是jffs2,yaffs和nfs网络文件系统。Jffs2文件系统是专为nor flash设计的文件系统,考虑到了nor flash的许多特性,同时具有压缩性能,一般可以达到2:1的压缩效果,但是在用于大于128Mbytes的flash时,效果不是太好。Yaffs文件系统是专为nand flash设计的文件系统,考虑到了nand falsh的许多的特性,但是不具有压缩性能,但其加载速度较快,使用于大容量存储的场合。除去以上文件类型的不同之外,linux提供统一的api操作函数,来实现对文件系统的管理。另外,在linux中,在对一个设备上的文件进行操作时,需要首先挂载这个设备到文件系统中,才能操作这个设备上的文件。在linux内核启动时,会默认挂载一个文件系统,这个就是根文件系统,此后所有的文件系统都是基于这个文件系统进行挂载,同时也可以卸载,但是根文件系统是不能卸载的。挂载一个文件系统的命令如下:mount t yaffs/dev/mtdblock0/mnt意思是说,把文件类型为yaffs的mtdblock0上的文件系统挂载到/mnt目录下,Linux进程调度,Linux 调度算法 Linux 调度算法把CPU 的时间划分为时期(epoch)。在一个单独的时期内,每个进程有一个指定的时间片,时间片持续时间从这个时期的开始计算。一般情况下,不同的进程有不同大小的时间片。时间片的值是在一个时期内,分配给进程的最大CPU时间部分。当一个进程用完它的时间片时,这个进程被抢占,并用另一个可运行进程代替它。当然,在同一时期内,一个进程可以几次被调度程序选中(只要它的时间片还没用完),例如,如果进程挂起自己,等待I/O,那么,它还剩余一些时间片,并可以在同一时期内再度被选中。当所有的可运行进程都用完它们的时间片时,一个时期才结束;在这种情况下,调度程序的算法重新计算所有进程的时间片,然后,一个新的时期开始。,Linux进程管理,Linux进程的优先级静态优先级(Static priority),这种优先级由用户赋给实时进程,范围从1 到99,调度程序从不改变它。动态优先级(Dynamic prority),这种优先级只应用于普通进程。实质上它是基本时间片由此也叫进程的基本优先级(base priority)与当前时期内的剩余时间片之和。当然,实时进程的静态优先级总是高于普通进程的动态优先级,只有当TASK_RUNNING 状态没有实时进程时,调度程序才开始运行普通进程。,Linux进程管理,Linux进程的创建在Linux中要使用exec函数族。系统调用execve()对当前进程进行替换,替换者为一个指定的程序,其参数包括文件名(filename)、参数列表(argv)以及环境变量(envp)。exec函数族当然不止一个,但它们大致相同,在Linux中,它们分别是:execl,execlp,execle,execv,execve和execvp,下面我只以execlp为例,其它函数究竟与execlp有何区别,请通过manexec命令来了解它们的具体情况。一个进程一旦调用exec类函数,它本身就死亡了,系统把代码段替换成新的程序的代码,废弃原有的数据段和堆栈段,并为新程序分配新的数据段与堆栈段,唯一留下的,就是进程号,也就是说,对系统而言,还是同一个进程,不过已经是另一个程序了。(不过exec类函数中有的还允许继承环境变量之类的信息。),Linux线程管理,使用线程的优点和进程相比,它是一种非常“节俭”的多任务操作方式(内存占用,启动时间,切换时间)和进程相比,线程间的通信更加方便。提高应用程序响应 使多CPU系统更加有效改善程序结构,复杂问题简单化,Linux线程管理,多线程的例子#include#include#include#include void thread(void)int i;for(i=0;i3;i+)printf(This is a pthreadn);usleep(100*1000);int main(void)pthread_t id;int i,ret;ret=pthread_create(,Linux线程管理,多线程的编译APP=threadTest$(APP):$(APP).cgcc-Wall-o$(APP)$(APP).c-lpthreadclean:rm$(APP),Linux进程间通信,Linux进程间通信的方法管道、消息队列、共享内存、信号量、套接口、信号,Linux进程间通信,管道管道包括无名管道和有名管道两种,前者用于父进程和子进程间的通信,后者用于运行于同一台机器上的任意两个进程间的通信无名管道无名管道由pipe()函数创建:int pipe(int filedis2);参数filedis返回两个文件描述符:filedes0为读而打开,filedes1为写而打开。filedes1的输出是filedes0的输入。,Linux进程间通信,无名管道的例子#include#include#include#include#include#define INPUT 0#define OUTPUT 1int main()int file_descriptors2;/*定义子进程号*/pid_t pid;char buf256;int returned_count;/*创建无名管道*/pipe(file_descriptors);/*创建子进程*/if(pid=fork()=-1)printf(Error in forkn);exit(1);,Linux进程间通信,无名管道的例子if(pid=0)/*执行子进程*/printf(child process.n);/*子进程向父进程写数据,关闭管道的读端*/close(file_descriptorsINPUT);write(file_descriptorsOUTPUT,test data,strlen(test data);exit(0);else/*执行父进程*/printf(parent process.n);/*父进程从管道读取子进程写的数据,关闭管道的写端*/close(file_descriptorsOUTPUT);returned_count=read(file_descriptorsINPUT,buf,sizeof(buf)-1);if(returned_count0)printf(receive data from child is errorn);return-1;bufreturned_count=0;printf(%d bytes of data received from child process:%sn,returned_count,buf);return 0;,Linux进程间通信,命名管道有名管道可由两种方式创建:命令行方式mknod系统调用和函数mkfifo。下面的两种途径都在当前目录下生成了一个名为myfifo的有名管道:方式一:mkfifo(myfifo,rw);方式二:mknod myfifo p 生成了有名管道后,就可以使用一般的文件I/O函数如open、close、read、write等来对它进行操作,Linux进程间通信,消息队列消息队列用于运行于同一台机器上的进程间通信。同一台机器中运行的所有进程都可以通过此消息对列向另一个进程发送消息。用于消息对列通信的函数有以下几个:intmsgget(key_tkey,intmsgflg);intmsgsnd(intmsgid,structmsgbuf*msgp,intmsgsz,intmsgflg);intmsgrcv(intmsgid,structmsgbuf*msgp,intmsgsz,longmsgtype,intmsgflg);intmsgctl(Intmsgid,intcmd,structmsqid_ds*buf);其中用于消息传递的消息数据的格式需要符合以下各式:struct msgbuf longmsgtype;/*消息类型*/./*其他数据类型*/,Linux进程间通信,共享内存共享内存是运行在同一台机器上的进程间通信最快的方式,因为数据不需要在不同的进程间复制。通常由一个进程创建一块共享内存区,其余进程对这块内存区进行读写。得到共享内存有两种方式:映射/dev/mem设备和内存映像文件。前一种方式不给系统带来额外的开销,但在现实中并不常用,因为它控制存取的将是实际的物理内存,在Linux系统下,这只有通过限制Linux系统存取的内存才可以做到,这当然不太实际。常用的方式是通过shmXXX函数族来实现利用共享内存进行存储的。首先要用的函数是shmget,它获得一个共享存储标识符。int shmget(key_t key,int size,int flag);这个函数有点类似大家熟悉的malloc函数,系统按照请求分配size大小的内存用作共享内存。Linux系统内核中每个IPC结构都有的一个非负整数的标识符,这样对一个消息队列发送消息时只要引用标识符就可以了。这个标识符是内核由IPC结构的关键字得到的,这个关键字,就是上面第一个函数的key,Linux进程间通信,共享内存当共享内存创建后,其余进程可以调用shmat()将其连接到自身的地址空间中。void*shmat(int shmid,void*addr,int flag);shmid为shmget函数返回的共享存储标识符,addr和flag参数决定了以什么方式来确定连接的地址,函数的返回值即是该进程数据段所连接的实际地址,进程可以对此进程进行读写操作。使用共享存储来实现进程间通信的注意点是对数据存取的同步,必须确保当一个进程去读取数据时,它所想要的数据已经写好了。通常,信号量被要来实现对共享存储数据存取的同步,另外,可以通过使用shmctl函数设置共享存储内存的某些标志位如SHM_LOCK、SHM_UNLOCK等来实现,Linux进程间通信,信号量信号量又称为信号灯,它是用来协调不同进程间的数据对象的,而最主要的应用是前一节的共享内存方式的进程间通信。本质上,信号量是一个计数器,它用来记录对某个资源(如共享内存)的存取状况。一般说来,为了获得共享资源,进程需要执行下列操作:(1)测试控制该资源的信号量。(2)若此信号量的值为正,则允许进行使用该资源。进程将进号量减1。(3)若此信号量为0,则该资源目前不可用,进程进入睡眠状态,直至信号量值大于0,进程被唤醒,转入步骤(1)。(4)当进程不再使用一个信号量控制的资源时,信号量值加1。如果此时有进程正在睡眠等待此信号量,则唤醒此进程。,Linux进程间通信,信号量信号量是一个数据集合,用户可以单独使用这一集合的每个元素。要调用的第一个函数是semget,用以获得一个信号量ID。int semget(key_t key,int nsems,int flag);key是前面讲过的IPC结构的关键字,它将来决定是创建新的信号量集合,还是引用一个现有的信号量集合。nsems是该集合中的信号量数。如果是创建新集合(一般在服务器中),则必须指定nsems;如果是引用一个现有的信号量集合(一般在客户机中)则将nsems指定为0。semctl函数用来对信号量进行操作。int semctl(int semid,int semnum,int cmd,union semun arg);不同的操作是通过cmd参数来实现的,在头文件sem.h中定义了7种不同的操作,实际编程时可以参照使用。semop函数自动执行信号量集合上的操作数组。nt semop(int semid,struct sembuf semoparray,size_t nops);semoparray是一个指针,它指向一个信号量操作数组。nops规定该数组中操作的数量。,Linux进程间通信,信号信号是在软件层次上对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的。信号是异步的,一个进程不必通过任何操作来等待信号的到达,事实上,进程也不知道信号到底什么时候到达。信号是进程间通信机制中唯一的异步通信机制,可以看作是异步通知,通知接收信号的进程有哪些事情发生了。信号机制经过POSIX实时扩展后,功能更加强大,除了基本通知功能外,还可以传递附加信息。,Linux进程间通信,信号的例子#include#include#include#include void signalCtrlC(int sig)printf(Got CTRL+C keyn);exit(0);int main()signal(SIGINT,signalCtrlC);while(1)sleep(1);return 0;,Linux进程间通信,套接字接口套接字接口(socket)编程是实现Linux系统和其他大多数操作系统中进程间通信的主要方式之一。我们熟知的WWW服务、FTP服务、TELNET服务以及我们现在正在做宽带网络信息服务等都是基于套接口编程来实现的。除了在异地的计算机进程间以外,套接口同样适用于本地同一台计算机内部的进程间通信。关于这部分的编程开发,会在以后的工作更多的接触到。,