Linux网络编程技术学习笔记
1.文件系统
Ext2 linux自身的文件系统
Msdos DOS文件系统
Vfat Windows95/98 vfat长文件名文件系统
iso9660 CDROM文件系统
Nfs 网络文件系统
Auto 系统自动判断文件系统类型
mount -t <fs_type><device><mount_point> 直接装载文件系统
umount<device>
umount<mount_point>
umount -a 卸下所有的文件系统
umount<fs_type> 卸下指定的文件系统
<device><mount_point>指定文件系统
2.进程控制块PCB
进程的静态表示为三个部分,程序部分,数据空间和进程控制块,将这三个统一称为进程映像
程序部分表述了进程所要完成的功能,是组成进程的主要部分,一个程序段可以被多个程序所共享,被共享的程序段应当被编写成纯代码
数据空间包含了程序段被执行时所需要的数据区和工作单元,并且是对应进程专用的.当进程使用的程序段不是纯代码时,将其作为数据的一部分放入数据空间
进程控制块PCB:每个进程都设有一个进程控制块,PCB是用来跟踪并记录动态变化的进程的各种调度信息的数据结构,它集中体现了进程动态变化的特征,进程的当前状态,进程和
其他进程的关系等.
3.操作系统是通过进程来完成一个个任务的,可以把进程看作在运行的程序。linux中每个进程都是由一个叫task_struct的结构体表示的.而task数组则包含了系统中只想每个task_struct
结构的指针,因此,一个系统的进程数目不能超过task进程的大小.缺省状态下有512项,当一个新进程被创建时,一个新的task_stuct从系统内存中分配出来,并在task数组中登记.
这里特殊约定,当前正在运行的进程其task_stuct由current指针指着.
当系统启动的时候,总有一个真正的进程.init进程,它的pid号为1,做了一些初始化工作,即启动init核心线程.其他所有的进程都是由这个进程通过fork系统调用创建的.
4. fork()调用的作用是使调用fork()的进程变成新创建进程的父进程.
一旦进程已经被创建,则父进程和子进程都成fork()调用内部继续执行,这意味着两个进程的下一个动作是带有它的返回值从fork()返回.
如果fork()确实返回一个0值,则它必须给新的子进程.如果它返回一个非零值,则它必须是返回给父进程的子进程的进程识别号(PID)(或者在错误的时候,返回-1).
fork系统调用创建子进程的做法,是把自己复制给子进程,就是说,新创建的进程是父进程的一个副本.继而子进程通过exec系统调用,用一个新的程序来覆盖子进程的内存空间,
从而执行那个新程序.系统调用exit可以终止一个进程的执行.子进程也常常用exit系统调用来自我终止,子进程终止之后,进入僵死(zombie)状态,父进程可通过执行wait系统调用来实现
与子进程的终止同步,接受子进程的返回状态和返回参数.
parent----------------(wait)---------------Parent
|fork |
| |
child----(exec)---->child-----(exit)------>zomb
5.linux系统调用简介
linux系统提供的系统调用借口大部分是C语言函数接口.
在操作系统中的每一个app(应用程序)或用户程序都必须依靠系统调用来完成对硬件的操作和对一些基本操作的实现.在linux中使用中断机制来实现系统调用,专门给操作系统的系统调
用一个中断0*80,从而保证了系统的高效性
6.exec系统调用
用户使用shell运行一个条命令时,则在某一时刻,shell将执行fork()调用使一个新进程运行.做完后,shell使用exec()调用来使ls命令在新进程中运行以代替在fork()调用后立即运行shell的副
本.由若干不同形式的exec()调用,都执行同样的任务.在linux系统中使用exec()系统调用是使程序执行的唯一方法.具体做法是:在使用exec()系统调用时,将程序文件的名字作为参数传递给
exec().然后它将包含在程序文件中的数据段来代替执行exec()调用的数据段.
exec()调用:
当系统从shell执行一个程序时,需要在命令行中为该程序指定参数和开关.从C语言的知识,你也知道这些命令的值是通过mian函数的参数argc和argv日共给程序使用嗯.shell需要能
以某种方式取命令行的值,并且把他们作为argc和argv,传递给运行的程序.这一任务由exec()调用来完成.将命令行的值以适当的值以适当的形式传递给它,他将安排他们作为将要运
行的新程序的argc和argv.
argc是参数个数.是各个参数字符串指针数组,envp是新进程的环境变量字符串的指针数组.argc至少为1,argv[0]为程序文件名.所以int execve(path,argv,envp)中的exec系统调用族中
path为新进程文件的路径名,file为新进程文件明.若file不是全路径名,系统调用组按PATH环境变量自动找对应的可执行文件运行.若新进程文件不是一个可执行的目标文件(如批处理文件)
则execlp和execvp会将文件哦你容作为一个命令解释器的标准输.Argv[0]等指针只想'\0'结束的字符串,组成新进程的有效参数,且该参数列表以一个空指针结束.反过来,arg0至少必须存在
并指向新进程个文件名活路径名.同样,argv是字符串指针数组,以空指针结束.这些字符串组策划嗯新进程的环境.在调用这些系统调用前打开的文件指针对新进程来说也是打开的,除非它
已定义了close-on-exec标志.打开的文件指针在新进程中保持不变,所有相关的文件锁也被保留.调用进程设置并正被捕俘的信号在新进程中被恢复为缺省这只,其他的则保持不变.新进程
启动时按文件的SUID和SGID设置定义文件的UID和GID为有效UID和UID和GID.
调用成功后,系统调用修改新进程文件的最新访问时间
例子:
#include<stdio.h>
main()
{
execl("/bin/ls","ls","-l",0);
printf("Can onlu get here on error\n");
}
在这个例子中,execl()的第一个参数是ls命令的完整参数路径名,假如进程对该文件有执行权限,这一文件内容将被执行.新程序的argv数组元素所只想字符串将由excl()的其余参数提供.
argv[0]元素所指向的字符串ls和由它argv[1]元素所指向的字符串-l
通常exec()调用并不返回,因为它的功能是用某个其他程序的数据段代替调用他们的进程数据段.
但是如果对exec()调用由于任何原因而失效,则它们将返回,使用户能有机会对错误进程处理.
用户希望一个运行的进程组织另一个程序的执行作为它的操作的一部分时,步骤:
第一步:运行的进程取得或产生要执行的命令
第二步:运行的进程执行fork()系统调用.它启动一个新进程,使原来进程的拷贝,并且与原来的进程并发的执行.原来的进程称为父进程,新进程称为子进程
第三步:现在的子进程执行exec()调用.它去掉子进程的用户数据段并且将要运行的在命令文件中的用户数据段代替它们.
出现问题:首先,用父进程的完整复制品来创建子进程,仅仅是为了立即去掉它并用新程序代替它是否是一种浪费?其次,当子进程正在执行时,父进程又在干什么?
linux()以一种非常有效的方式实现的它的fork()系统调用.事实上,linux并没有复制进程的完整拷贝,它只用两组指针,每个进程对应一组,全部只想同一实际的数据段.虽然父进程和子进程是
一对独立的进程,但只要两个进程仅仅从数据段读数据而不写任何新值,就不会发生问题.当两个进程之一企图将数据写道数据段之一时,能发现它,并且按需要对数据段的这一区域进行复制
这一技术被称为在写时复制(copy on write).
从原则上讲,由任何一个进程写的任何的区域将得到复制,是的两个进程都有他们自己的这些区域的副本.如果子进程立即执行exec()调用,则在执行exec()调用之前只有少量的共享数据段
被复制,因而大量节省了时间和资源