UNIX常用系统函数
UNIX系统常用命令
UNIX系统常用命令UNIX系统常用命令格式:command [flags] [argument1] [argument2] ...其中flags以-开始,多个flags可用一个-连起来,如ls -l -a 与ls -la相同。
根据命令的不同,参数分为可选的或必须的;所有的命令从标准输入接受输入,输出结果显示在标准输出,而错误信息则显示在标准错误输出设备。
可使用重定向功能对这些设备进行重定向。
命令在正常执行结果后返回一个0值,如果命令出错可未完全完成,则返回一个非零值(在shell中可用变量$?查看). 在shell script中可用此返回值作为控制逻辑的一部分。
注:不同的UNIX版本的flags可能有所不同。
1、与用户相关的命令1.1 login(在LINUX Redhat下此命令功能与Solaris/BSD不同,执行login会退出当前任务).login:Password:相关文件:在下面的这些文件中设定shell运行时必要的路径,终端类型,其他变量或特殊程序.$HOME/.profile (Bourne shell, sh, bash)$HOME/.cshrc (csh, tcsh)$HOME/.tcshrc (tcsh)/etc/passwd文件中列出每个用户的shell/etc/csh.cshrc/etc/csh.login/etc/profile (Bourne shell, bash)/etc/login (Bourne shell, bash)csh: /etc/csh.cshrc和$HOME/.cshrc每次执行都会读取,而/etc/csh.login和$HOME/.login只有注册shell才执行修改相应文件后使用 source .cshrc使能相关修改,如果修改了path则还需使用rehash刷新可执行文件hash表。
tcsh: $HOME/.tcshrc, 没有些文件读取.cshrcsh: /etc/profile和$HOME/.profile注册shellbash: /etc/profile和$HOME/.bash_profile注册shell读取.bashrc交互式非注册shell才读取。
unx常用命令介绍
1.1帮助命令man (2)1.1.1按章节寻找帮助 (2)1.1.2按照关键字寻找帮助 (2)1.2环境变量 (2)1.3目录操作命令 (3)1.4文件操作命令 (3)1.4.1链接命令ln (3)1.4.2显示文件 (3)1.4.3拷贝文件和文件改名、文件移动 (4)1.4.4删除文件 (4)1.4.5改变文件和目录的属主和访问权限 (5)1.4.6查找文件命令find (5)1.4.7文件压缩工具tar (6)1.5文件内容查询命令grep (6)1.6文件内容查看和编辑 (6)1.7重定向和管道 (7)1.8网络命令 (8)1.9其它常用命令 (8)1.10编译程序cc (8)UNIX常用命令介绍1.1帮助命令manunix的帮助手册分为多个章节,常用的有第1、2、3节,分别包括用户命令、系统调用、和C 库函数。
在一些版本的unix中,又分了一些小的章节,比如:1B、3C这样的标题,把帮助的分类进一步的细化,在unix中,帮助文件存放在/usr/share/man下,按章节存放。
下面介绍命令man通常的用法:1.1.1按章节寻找帮助寻找用户命令time的帮助和寻找系统调用time的帮助分别为(在不同的unix版本,命令的用法不一样,下面是在Solaris上的用法):$ man –s 1 time$ man –s 2 time如果不带章节参数的话,系统会显示找到的第一个命令的帮助(按章节的先后)。
有的系统支持-a参数,显示所有章节的帮助,比如显示time在所有章节中的帮助:$ man –a time1.1.2按照关键字寻找帮助下面的命令列出所有跟time相关的帮助信息:$man –k time1.2环境变量在unix中,shell可以维护一些变量,在变量中存放一些数据供以后使用。
显示当前的环境变量:$ env给变量赋值:$ MYHOME=/export/home/xubr; export MYHOME$ MYPATH=$PATH:/export/home/xubr; export MYPA TH查看变量的值:$ echo $MYPATH1.3目录操作命令类似windows,在unix中,某目录中的一个点表示当前目录、两个点表示上级目录,同样支持绝对路径和相对路径。
UNIX基础
rwxr-x--x 方
111101001
法 一
75 1
方 法 二
作用 用于非正常中断程序的运行 用于系统通信的中断 用来告诉终端,停止接受输入 告诉终端重新接受输入
# stty -a 显示所有的终端选项
UNIX的基本操作
清除屏幕命令
$ clear
UNIX的基本操作
系统帮助
$ man find
UNIX的基本操作
UNIX系统的关闭
# shutdown –hy 0
UNIX的基本操作 目录操作类命令 文件浏览类命令 文件管理类命令
滤通类命令 系统资源类命令 网络操作类命令
vi的常用命令 系统维护类命令
UNIX的基本操作
内容
UNIX的登录与退出 UNIX用户的切换 UNIX命令行的使用 UNIX控主制机键的的开使机用与关机
清除屏幕 UNIX系统的在线帮助 UNIX系统的重启与关闭
UNIX操作-目录
目录操作命令
ls:显示目录内容 格式:ls [option] [path]
[path]:绝对路径、相对路径
[optin]: -l:显示文件所有属性 -a:显示所有文件含隐含文件 如.profile -s:显示文件占用的block数
UNIX操作-文件的类型与权限
$ ls -l sort -rwxr-x--x 1 myname mygroup 120 Jul 26 10:20 sort
UNIX基础
集成产品部
内容
UNIX操作系统概述 UNIX常用操作命令使用
UNIX简介
内容
UNIX流派与标准 UNIX的特点 UNIX系统组成
UNIX的shell程序 UNIX的用户
UNIX操作系统常用功能操作系统常用命令
UNIX操作系统常用功能ls功能:显示指定工作目录下之内容语法:ls [参数选项][目录名]说明:显示指定工作目录下的内容参数选项:如下图选项选项说明-a 显示所有文档及目录,包括隐藏文件-l 将文档名、文档类型、权限、拥有者、大小等信息详细列出-r 将文档以相反次序显示(原定按英文字母次序)-t 将文档依修改时间之先后次序列出-A 同 -a ,但不列出“.” (当前目录) 及 ".." (父目录)-F 在列出的文档名称后加一符号;例如可执行文档则加“*”,目录则加“/”,符号链接文件加“@”-R 递归地显示子目录中的内容Dir功能:同 lscd功能:变换工作目录语法:cd [目录名]说明:用于更换工作目录例题:如下1、cd .. 更换目录回到上一级目录2、cd . 更换到当前目录3、cd ~ 更换目录到当前用户的个人宿主目录4、cd /etc/vsftpd/ 更换到/etc/vsftpd目录5、cd / 更换目录到根目录pwd功能:显示用户当前的工作路径,显示出完整的当前活动目录名称。
语法:pwd说明:显示当前工作目录的绝对路径clear功能:在允许的情况下清除屏幕语法:clear说明:清楚屏幕上的信息man功能:查看指令用法的help语法:man [参数选项] 帮助主题。
说明:man实际上就是查看命令用法的help,学习任何一种UNIX类的操作系统最重要的就是学会使用man这个辅助功能。
man是manual(手册)的缩写字,它的说明非常的详细,建议记得一些基本用法就可以了。
mkdir功能:用来建立新的目录语法:mkdir [参数选项] 目录名说明:创建一个空目录,要求此用户在当前目录上具有写权限参数选项:如下图选项选项说明-m mode 为新目录设置访问模式。
-p 如果父目录不存在,创建所有的父目录。
rmdir功能:用来删除已建立的目录语法:rmdir [参数选项]目录名说明:删除一个或多个空目录或空子目录,要求此用户在当前目录上具有写权限rm功能:删除文档及目录。
sys_fork函数讲解
sys_fork函数讲解【原创实用版】目录1.sys_fork 函数的概念和作用2.sys_fork 函数的调用方式和参数3.sys_fork 函数的返回值4.sys_fork 函数的实际应用正文sys_fork 函数是 Unix 系统中的一个重要函数,主要用于创建一个与原来进程几乎完全相同的进程。
该函数可以用于实现多进程程序设计,是操作系统中进程管理的基础。
一、sys_fork 函数的概念和作用sys_fork 函数是 Unix 系统中的一个系统调用函数,其主要作用是创建一个新的进程。
这个新进程与原进程在代码和数据上是完全相同的,不同的只是进程 ID。
sys_fork 函数在进程创建的过程中,将原进程的代码、数据和打开的文件描述符等资源进行复制,从而创建一个新的进程。
二、sys_fork 函数的调用方式和参数sys_fork 函数的调用方式与其他系统调用函数类似,都是通过调用 int sys_fork(void) 函数来实现。
该函数没有参数,调用后返回两个值:若成功调用,则返回 0,表示新进程已经创建成功,原进程的进程 ID 为 0;若失败,则返回 -1,表示调用失败。
三、sys_fork 函数的返回值sys_fork 函数的返回值具有一定的特殊性。
当函数调用成功时,返回的值是两个,分别是 0 和子进程的进程 ID。
0 表示新进程已经创建成功,而子进程的进程 ID 则表示新进程的具体 ID。
当函数调用失败时,返回的值为 -1,表示调用失败。
四、sys_fork 函数的实际应用sys_fork 函数在实际应用中主要用于创建多进程程序。
通过不断地调用sys_fork 函数,可以创建大量的进程。
这些进程可以用于执行不同的任务,从而实现程序的并发和并行。
sys_fork 函数还可以用于创建一个子进程,然后对子进程进行操作,如设置进程优先级、修改进程的文件描述符等。
综上所述,sys_fork 函数是 Unix 系统中进程管理的基础,它可以用于创建一个与原来进程几乎完全相同的进程。
UNIX常用命令介绍
2.4 UNIX常用命令介绍用户对某一操作系统的认识,往往是从使用和接触操作系统开始的,而接触操作系统最常用的方法就是使用操作系统的命令。
尽管现代操作系统都对用户提供交互式的图形界面,但在使用操作系统时仍不可避免地要用到命令操作方式,这是因为图形界面的处理也是建立在命令处理的基础之上的。
有经验的人都知道,使用命令处理的效率往往会比使用图形界面处理高出很多,而可视化的图形界面主要解决的问题是提供友好交互和摆脱枯燥的命令记忆方式。
2.4.1 UNIX命令使用方法当某个用户正确地通过了系统的注册和登录后,就进入到UNIX的命令管理程序shell的第一个进程中。
shell可以完成UNIX命令的解释执行过程,它大体上可以分成两类:一类是s hell的内部命令,另一类是shell的外部命令。
对用户来讲,内、外部命令在使用方法上没有太多的差异,只是在响应时间上略有不同。
当用户发出内部命令时,系统可直接从内存中选择调用与执行。
而shell的外部命令是那些功能较强、占用空间较大的扩展命令,它们一般不包含在shell中,因此在系统启动时并不被装入内存,只是在使用时才从系统的指定存储介质中调入内存,用完后就释放所占用的内存空间。
外部命令往往功能强大,因此所占用的磁盘空间和内存空间都比较大,甚至有些外部命令实际上就是一个实用程序,它所占用的空间和处理过程的复杂度可以与一个小型系统规模相比,因此对外部命令的管理通常包含着对内、外存空间的控制和管理。
1. UNIX的命令格式使用UNIX命令的方法可以有多种,例如,可以在命令行上输入命令,或是将命令编写在批处理文件中。
无论怎样,命令的使用格式是统一的,UNIX的一般命令格式为:Command[-options][arguments]其中:Command表示UNIX命令名。
[options]表示命令的执行选项,可以取默认值。
[arg uments]表示命令的执行参数,可以默认。
常用系统函数介绍
常用系统函数介绍系统函数是很多编程语言中的关键部分,它们提供了一系列强大的功能来处理各种任务。
在本文中,我将介绍一些常用的系统函数,以及它们的功能和用法。
1. print函数print函数是一种常见的用于输出信息的系统函数。
它可以接受一个或多个参数,并将其打印到标准输出。
例如,我们可以使用print函数来输出一条消息:```print("Hello World!")```2. input函数input函数用于接受用户输入的数据。
它可以显示一个提示消息,并等待用户输入信息,然后将输入信息作为返回值返回。
例如,我们可以使用input函数来获取用户的姓名:```name = input("Please enter your name: ")```3. len函数len函数用于获取指定对象的长度或大小。
它可以用于字符串、列表、元组等各种数据结构。
例如,我们可以使用len函数来获取一个字符串的长度:```str = "Hello World!"length = len(str)print(length) # 输出:12```4. range函数range函数用于生成一个指定范围内的整数序列。
它可以接受一个或多个参数,并根据参数的不同生成不同类型的序列。
例如,我们可以使用range函数生成一个从0到9的整数序列:```for i in range(10):print(i) # 输出:0, 1, 2, 3, 4, 5, 6, 7, 8, 9```5. type函数type函数用于获取指定对象的类型。
它可以返回一个字符串,表示对象所属的类型。
例如,我们可以使用type函数来判断一个变量的类型:```print(type(x)) # 输出:<class 'int'>```6. str函数str函数用于将指定对象转换为字符串类型。
signal函数的使用
signal函数的使用signal系统函数调用提供了一种最简单的范例。
然而,由于C原形声明的缘故使它看起来比实际复杂。
signal函数将一个给定的函数和一个特定的信号联系。
这里是FreeBSD中的定义(和一个typedef一起):引用:typedef void (*sig_t) (int);sig_t signal(int sig, sig_t func);第一个参数是目标信号。
func参数是一个指针,指向某个处理该信号的函数。
这个处理信号函数带有一个int型参数,并应返回void。
signal函数中的func参数也可以设定为下面的一些值:引用:SIG_IGN: 如果func参数被设置为SIG_IGN,该信号将被忽略。
SIG_DFL: 如果func参数被设置为SIG_DFL,该信号会按照确定行为处理。
PS:sig信号的可能类型:#define SIGHUP 1 /* hangup */SIGHUP是Unix系统管理员很常用的一个信号。
许多后台服务进程在接受到该信号后将会重新读取它们的配置文件。
然而,该信号的实际功能是通知进程它的控制终端被断开。
缺省行为是终止进程。
#define SIGINT 2 /* interrupt */对于Unix使用者来说,SIGINT是另外一个常用的信号。
许多shell的CTRL-C组合使得这个信号被大家所熟知。
该信号的正式名字是中断信号。
缺省行为是终止进程。
#define SIGQUIT 3 /* quit */SIGQUIT信号被用于接收shell的CTRL-/组合。
另外,它还用于告知进程退出。
这是一个常用信号,用来通知应用程序从容的(译注:即在结束前执行一些退出动作)关闭。
缺省行为是终止进程,并且创建一个核心转储。
#define SIGILL 4 /* illegal instr. (not reset when caught) */如果正在执行的进程中包含非法指令,操作系统将向该进程发送SIGILL信号。
fork函数 用法
fork函数用法**标题:fork函数用法详解****一、概述**fork函数是Unix/Linux操作系统中常用的系统调用之一,它用于创建一个新的进程,并返回新进程的进程ID。
这个函数是在调用进程中创建新进程的基础,可以在当前进程的基础上,生成一个新的子进程,父进程和子进程之间可以共享一些数据,但是也必须考虑并发环境中的安全问题。
**二、函数原型**在Unix/Linux系统中,fork函数的基本原型为:intfork(void)。
这个函数会在调用它的进程中创建一个新的进程,并返回两个值:新创建的子进程的进程ID和父进程的进程ID。
如果返回值为-1,则表示fork函数调用失败。
**三、使用场景**fork函数主要用于创建一个新的进程,该进程继承了父进程的环境和状态。
在多线程或多进程编程中,fork函数可以帮助我们更好地管理并发环境中的资源。
例如,在父进程中创建一个新的子进程来执行一些特定的任务,子进程可以继承父进程的一些资源(如打开的文件描述符),而父进程则可以继续执行其他任务。
**四、注意事项**在使用fork函数时,需要注意以下几点:1. fork函数会创建一个新的进程,并返回两个值。
因此,需要确保在调用fork函数之前已经正确地分配了足够的内存空间来保存返回的两个值。
2. fork函数创建的新进程与原进程共享一些资源(如打开的文件描述符),但也需要注意并发环境中的安全问题。
例如,需要确保在子进程中关闭父进程打开的文件描述符,以避免资源泄漏。
3. 在子进程中执行一些操作时,需要考虑到父进程的状态和环境。
例如,如果父进程正在等待某个条件成立(如某个文件被修改),则需要考虑到子进程是否会改变这个条件。
4. fork函数在创建新进程时,会复制一部分父进程的内存空间到新的子进程中。
因此,如果父进程的内存空间非常大,则创建子进程所消耗的时间和内存也会相应增加。
**五、示例代码**下面是一个简单的示例代码,展示了fork函数的使用方法:```c#include <stdio.h>#include <unistd.h>#include <sys/types.h>int main() {pid_t pid; // 用于保存新创建的子进程的进程ID// 调用fork函数创建新进程pid = fork();// 判断fork函数是否成功if (pid < 0) {printf("Fork failed!\n");return 1;} else if (pid == 0) { // 子进程结束循环执行完毕后返回0,否则返回-1结束程序运行// 子进程代码段...while(1) { // 循环执行一些任务...} } else { // 父进程代码段...} // 父进程继续执行其他任务...}```六、总结**fork函数是Unix/Linux系统中的一个重要系统调用,用于在调用进程中创建一个新的子进程。
uinux常用命令
UNIX常用命令以下只说明各常用指令的基本用法, 若需详细说明, 请用 man 去读详细的 manual.1.关於档案/目录处理的命令ls——列目录这是最基本的档案指令。
ls 的意义为 "list",也就是将某一个目录或是某一个档案的内容显示出来。
格式:ls -1ACFLRabcdfgilmnopqrstux -W[sv] [files]例:#ls (不跟任何参数以简单格式列出当前目录中所有档案)#ls bin (简单格式列出名为bin的文件或目录下的所有档案)#ls /u/ilasII_GB/lib (全路径,列出lib目录下的所有档案)ls 的常用参数如下:-a : 在 UNIX 中若一个目录或档案名字的第一个字元为 "." , 则使用 ls将不会显示出这个档案的名字,我们称此类档案为隐藏档。
如 .profile、.tcshrc等如果我们要察看这类档案,则必须在其后加上参数 -a 。
-l : 这个参数代表使用 ls 的长( long )格式,可以显示更多的资讯,如档案存取权,档案拥有者( owner ),档案归属组,档案大小,档案最後更新时间,甚而 symbolic link 的档案是 link 那一个档等等。
显示结果如下所示:drwxrwxrwx 30 root bin 1024 May 23 10:38 udrwxrwxrwx 2 root sys 512 Jul 28 1999 uacndrwxrwxrwx 5 root sys 512 Jul 27 1999 udklrwxrwxrwx 1 root sys 11 Jul 27 1999 unix -> /stand/unixdrwxrwxrwx 35 root auth 1024 Apr 3 13:45 usr在开始的10个字符上系统给出文件的用户权限。
该序列分成四个域。
第一个字符为类型域,第2、3、4个字符为用户主域,第5、6、7个字符为同组用户域,第8、9、10个字符为其它用户域,域中字符的含义如下:? 在类型域中:d 表示此文件是一个目录- 表示此文件是一个普通文件b 表示此文件是一个特殊的块设备I/O文件c 表示此文件是一个特殊的字符设备I/O文件l 表示此文件是一个连接文件。
unix下read与write函数
• 这些问题不必过分强调:
现代计算机的可靠性很高,而且unix实 现的可靠性也很高,因此出现内核崩溃的几率 很小。大多数用户只会发现缓冲区的速度之快, 永远不会发现内核错误.
• 【 read系统调用】
功能描述: 从文件读取数据。
用法: #include <unistd.h> ssize_t read(int fd, void *buf, size_t nbytes); • 参数: fd: 将要读取数据的文件描述符。 buf: 所读取到的数据的内存缓冲。 count: 需要读取的数据量
• 【write系统调用】 • 功能描述:
向指定文件写数据 • 用法:
#include<unistd.h> ssize_t write(
int fd, //file descriptor const void *buf, //data to write size_t nbytes //amount to write )
除了声明如下内容外,不做其他事情:
我注意到了你的请求,接下来会保证你的文件 描述符可以使用。我已成功的复制了你的数据, 磁盘空间是充足的。以后我方便的时候,如果我 仍然是激活的,我会设法把你的数据放到磁盘中 去。如果发生错误,我会设法在控制台输出错误, 但我不会告诉你这些的(实际上,你那时可能已 经终止运行了)。如果我写出这些数据之前,你 或者其他进程试图读这些数据,那么我将从缓冲 区为你读这些数据,因此,如果一切顺利,你不 会知道我什么时候完成的请求,也不会知道是否 完成了请求,你可以进一步提出要求
• 说明:
• read函数可以读取文件。读取文件指从某一 个已打开地文件中,读取一定数量地字符, 然后将这些读取的字符放入某一个预存的缓 冲区内,供以后使用。
LinuxUnixtime时间戳的处理转换函数
LinuxUnixtime时间戳的处理转换函数Linux/Unix time时间戳的处理转换函数linux下的时间函数我们在编程中可能会经常⽤到时间,⽐如取得系统的时间(获取系统的年、⽉、⽇、时、分、秒,星期等),或者是隔⼀段时间去做某事,那么我们就⽤到⼀些时间函数。
linux下存储时间常见的有两种存储⽅式:⼀个是从1970年到现在经过了多少秒;⼀个是⽤⼀个结构来分别存储年⽉⽇时分秒的。
time_t 这种类型就是⽤来存储从1970年到现在经过了多少秒,要想更精确⼀点,可以⽤结构struct timeval,它精确到微妙。
1struct timeval2 {3long tv_sec; /*秒*/4long tv_usec; /*微秒*/5 };⽽直接存储年⽉⽇的是⼀个结构:1struct tm2 {3int tm_sec; /*秒,正常范围0-59,但允许⾄61*/4int tm_min; /*分钟,0-59*/5int tm_hour; /*⼩时, 0-23*/6int tm_mday; /*⽇,即⼀个⽉中的第⼏天,1-31*/7int tm_mon; /*⽉,从⼀⽉算起,0-11*/8int tm_year; /*年,从1900⾄今已经多少年*/9int tm_wday; /*星期,⼀周中的第⼏天,从星期⽇算起,0-6*/10int tm_yday; /*从今年1⽉1⽇到⽬前的天数,范围0-365*/11int tm_isdst; /*⽇光节约时间的旗标*/12 };需要特别注意的是,年份是从1900年起⾄今多少年,⽽不是直接存储如2008年,⽉份从0开始的,0表⽰⼀⽉,星期也是从0开始的, 0表⽰星期⽇,1表⽰星期⼀。
下⾯介绍⼀下我们常⽤的时间函数:1 #include <time.h>23char *asctime(const struct tm* timeptr); //将结构中的信息转换为真实世界的时间,以字符串的形式显⽰;45char *ctime(const time_t *timep); //将timep转换为真是世界的时间,以字符串显⽰,它和asctime不同就在于传⼊的参数形式不⼀样;67double difftime(time_t time1, time_t time2); //返回两个时间相差的秒数;89int gettimeofday(struct timeval *tv, struct timezone *tz); //返回当前距离1970年的秒数和微妙数,后⾯的tz是时区,⼀般不⽤;1011struct tm* gmtime(const time_t *timep); //将time_t表⽰的时间转换为没有经过时区转换的UTC时间,是⼀个struct tm结构指针;1213 stuct tm* localtime(const time_t *timep); //和gmtime类似,但是它是经过时区转换的时间。
unix网络编程
[size=16]UNIX网络编程[/size]1.1 客户端程序和服务端程序网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端.网络程序是先有服务器程序启动,等待客户端的程序运行并建立连接.一般的来说是服务端的程序在一个端口上监听,直到有一个客户端的程序发来了请求.1.2 常用的命令由于网络程序是有两个部分组成,所以在调试的时候比较麻烦,为此我们有必要知道一些常用的网络命令netstat命令netstat是用来显示网络的连接,路由表和接口统计等网络的信息.netstat有许多的选项我们常用的选项是-an 用来显示详细的网络状态.至于其它的选项我们可以使用帮助手册获得详细的情况.telnettelnet是一个用来远程控制的程序,但是我们完全可以用这个程序来调试我们的服务端程序的. 比如我们的服务器程序在监听8888端口,我们可以用telnet localhost 8888来查看服务端的状况.1.3 TCP/UDP介绍TCP(Transfer Control Protocol)传输控制协议是一种面向连接的协议,当我们的网络程序使用这个协议的时候,网络可以保证我们的客户端和服务端的连接是可靠的,安全的.UDP(User Datagram Protocol)用户数据报协议是一种非面向连接的协议,这种协议并不能保证我们的网络程序的连接是可靠的,所以我们现在编写的程序一般是采用TCP协议的.2. 初等网络函数介绍(TCP)unix系统是通过提供套接字(socket)来进行网络编程的.网络程序通过socket和其它几个函数的调用,会返回一个通讯的文件描述符,我们可以将这个描述符看成普通的文件的描述符来操作,这就是unix的设备无关性的好处.我们可以通过向描述符读写操作实现网络之间的数据交流.2.1 socketint socket(int domain, int type,int protocol)domain:说明我们网络程序所在的主机采用的通讯协族(AF_UNIX和AF_INET等). AF_UNIX只能够用于单一的Unix系统进程间通信,而AF_INET是针对Internet的,因而可以允许在远程主机之间通信(当我们man socket时发现domain可选项是PF_*而不是AF_*,因为glibc是posix的实现所以用PF代替了AF,不过我们都可以使用的).type:我们网络程序所采用的通讯协议(SOCK_STREAM,SOCK_DGRAM等) SOCK_STREAM表明我们用的是TCP协议,这样会提供按顺序的,可靠,双向,面向连接的比特流. SOCK_DGRAM 表明我们用的是UDP协议,这样只会提供定长的,不可靠,无连接的通信.protocol:由于我们指定了type,所以这个地方我们一般只要用0来代替就可以了socket为网络通讯做基本的准备.成功时返回文件描述符,失败时返回-1,看errno可知道出错的详细情况.2.2 bindint bind(int sockfd, struct sockaddr *my_addr, int addrlen)sockfd:是由socket调用返回的文件描述符.addrlen:是sockaddr结构的长度.my_addr:是一个指向sockaddr的指针. 在<unix/socket.h>;中有sockaddr的定义struct sockaddr{unisgned short as_family;char sa_data[14];};不过由于系统的兼容性,我们一般不用这个头文件,而使用另外一个结构(struct sockaddr_in) 来代替.在<unix/in.h>;中有sockaddr_in的定义struct sockaddr_in{unsigned short sin_family;unsigned short int sin_port;struct in_addr sin_addr;unsigned char sin_zero[8];我们主要使用Internet所以sin_family一般为AF_INET,sin_addr设置为INADDR_ANY 表示可以和任何的主机通信,sin_port是我们要监听的端口号.sin_zero[8]是用来填充的. bind将本地的端口同socket返回的文件描述符捆绑在一起.成功是返回0,失败的情况和socket一样2.3 listenint listen(int sockfd,int backlog)sockfd:是bind后的文件描述符.backlog:设置请求排队的最大长度.当有多个客户端程序和服务端相连时, 使用这个表示可以介绍的排队长度. listen函数将bind的文件描述符变为监听套接字.返回的情况和bind一样.2.4 acceptint accept(int sockfd, struct sockaddr *addr,int *addrlen)sockfd:是listen后的文件描述符.addr,addrlen是用来给客户端的程序填写的,服务器端只要传递指针就可以了. bind,listen 和accept是服务器端用的函数,accept调用时,服务器端的程序会一直阻塞到有一个客户程序发出了连接. accept成功时返回最后的服务器端的文件描述符,这个时候服务器端可以向该描述符写信息了. 失败时返回-12.5 connectint connect(int sockfd, struct sockaddr * serv_addr,int addrlen)sockfd:socket返回的文件描述符.serv_addr:储存了服务器端的连接信息.其中sin_add是服务端的地址addrlen:serv_addr的长度connect函数是客户端用来同服务端连接的.成功时返回0,sockfd是同服务端通讯的文件描述符失败时返回-1.2.6 实例服务器端程序/******* 服务器程序(server.c) ************/#include <stdlib.h>;#include <stdio.h>;#include <errno.h>;#include <string.h>;#include <netdb.h>;#include <sys/types.h>;#include <netinet/in.h>;#include <sys/socket.h>;int main(int argc, char *argv[]){int sockfd,new_fd;struct sockaddr_in server_addr;struct sockaddr_in client_addr;int sin_size,portnumber;char hello[]="Hello! Are You Fine?\n";if(argc!=2){fprintf(stderr,"Usage:%s portnumber\a\n",argv[0]); exit(1);}if((portnumber=atoi(argv[1]))<0){fprintf(stderr,"Usage:%s portnumber\a\n",argv[0]); exit(1);}/* 服务器端开始建立socket描述符*/if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1) {fprintf(stderr,"Socket error:%s\n\a",strerror(errno)); exit(1);}/* 服务器端填充sockaddr结构*/bzero(&server_addr,sizeof(struct sockaddr_in));server_addr.sin_family=AF_INET;server_addr.sin_addr.s_addr=htonl(INADDR_ANY);server_addr.sin_port=htons(portnumber);/* 捆绑sockfd描述符*/if(bind(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1) {fprintf(stderr,"Bind error:%s\n\a",strerror(errno));exit(1);}/* 监听sockfd描述符*/if(listen(sockfd,5)==-1){fprintf(stderr,"Listen error:%s\n\a",strerror(errno));exit(1);}{/* 服务器阻塞,直到客户程序建立连接*/sin_size=sizeof(struct sockaddr_in);if((new_fd=accept(sockfd,(struct sockaddr *)(&client_addr),&sin_size))==-1) {fprintf(stderr,"Accept error:%s\n\a",strerror(errno));exit(1);}fprintf(stderr,"Server get connection from %s\n",inet_ntoa(client_addr.sin_addr));if(write(new_fd,hello,strlen(hello))==-1){fprintf(stderr,"Write Error:%s\n",strerror(errno));exit(1);}/* 这个通讯已经结束*/close(new_fd);/* 循环下一个*/}close(sockfd);}客户端程序/******* 客户端程序client.c ************/ #include <stdlib.h>;#include <stdio.h>;#include <errno.h>;#include <string.h>;#include <netdb.h>;#include <sys/types.h>;#include <netinet/in.h>;#include <sys/socket.h>;int main(int argc, char *argv[]){int sockfd;char buffer[1024];struct sockaddr_in server_addr;struct hostent *host;int portnumber,nbytes;if(argc!=3){fprintf(stderr,"Usage:%s hostname portnumber\a\n",argv[0]); exit(1);}if((host=gethostbyname(argv[1]))==NULL){fprintf(stderr,"Gethostname error\n");exit(1);}if((portnumber=atoi(argv[2]))<0){fprintf(stderr,"Usage:%s hostname portnumber\a\n",argv[0]); exit(1);}/* 客户程序开始建立sockfd描述符*/if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1){fprintf(stderr,"Socket Error:%s\a\n",strerror(errno));exit(1);}/* 客户程序填充服务端的资料*/bzero(&server_addr,sizeof(server_addr));server_addr.sin_family=AF_INET;server_addr.sin_port=htons(portnumber);server_addr.sin_addr=*((struct in_addr *)host->;h_addr);/* 客户程序发起连接请求*/if(connect(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1) {fprintf(stderr,"Connect Error:%s\a\n",strerror(errno));exit(1);}/* 连接成功了*/if((nbytes=read(sockfd,buffer,1024))==-1){fprintf(stderr,"Read Error:%s\n",strerror(errno));exit(1);}buffer[nbytes]='\0';printf("I have received:%s\n",buffer);/* 结束通讯*/close(sockfd);exit(0);}MakeFile这里我们使用GNU 的make实用程序来编译. 关于make的详细说明见Make 使用介绍######### Makefile ###########all:server clientserver:server.cgcc $^ -o $@client:client.cgcc $^ -o $@运行make后会产生两个程序server(服务器端)和client(客户端) 先运行./server portnumber& (portnumber随便取一个大于1204且不在/etc/services中出现的号码就用8888好了),然后运行 ./client localhost 8888 看看有什么结果. (你也可以用telnet和netstat试一试.) 上面是一个最简单的网络程序,不过是不是也有点烦.上面有许多函数我们还没有解释. 我会在下一章进行的详细的说明.2.7 总结总的来说网络程序是由两个部分组成的--客户端和服务器端.它们的建立步骤一般是:服务器端socket-->;bind-->;listen-->;accept客户端socket-->;connect3. 服务器和客户机的信息函数这一章我们来学习转换和网络方面的信息函数.3.1 字节转换函数在网络上面有着许多类型的机器,这些机器在表示数据的字节顺序是不同的, 比如i386芯片是低字节在内存地址的低端,高字节在高端,而alpha芯片却相反. 为了统一起来,在unix下面,有专门的字节转换函数.unsigned long int htonl(unsigned long int hostlong)unsigned short int htons(unisgned short int hostshort)unsigned long int ntohl(unsigned long int netlong)unsigned short int ntohs(unsigned short int netshort)在这四个转换函数中,h 代表host, n 代表network.s 代表short l 代表long 第一个函数的意义是将本机器上的long数据转化为网络上的long. 其他几个函数的意义也差不多.3.2 IP和域名的转换在网络上标志一台机器可以用IP或者是用域名.那么我们怎么去进行转换呢?struct hostent *gethostbyname(const char *hostname)struct hostent *gethostbyaddr(const char *addr,int len,int type)在<netdb.h>;中有struct hostent的定义struct hostent{char *h_name; /* 主机的正式名称*/char *h_aliases; /* 主机的别名*/int h_addrtype; /* 主机的地址类型AF_INET*/int h_length; /* 主机的地址长度对于IP4 是4字节32位*/char **h_addr_list; /* 主机的IP地址列表*/}#define h_addr h_addr_list[0] /* 主机的第一个IP地址*/gethostbyname可以将机器名(如)转换为一个结构指针.在这个结构里面储存了域名的信息gethostbyaddr可以将一个32位的IP地址(C0A80001)转换为结构指针.这两个函数失败时返回NULL 且设置h_errno错误变量,调用h_strerror()可以得到详细的出错信息3.3 字符串的IP和32位的IP转换.在网络上面我们用的IP都是数字加点(192.168.0.1)构成的, 而在struct in_addr结构中用的是32位的IP, 我们上面那个32位IP(C0A80001)是的192.168.0.1 为了转换我们可以使用下面两个函数int inet_aton(const char *cp,struct in_addr *inp)char *inet_ntoa(struct in_addr in)函数里面a 代表ascii n 代表network.第一个函数表示将a.b.c.d的IP转换为32位的IP,存储在inp指针里面.第二个是将32位IP转换为a.b.c.d的格式.3.4 服务信息函数在网络程序里面我们有时候需要知道端口.IP和服务信息.这个时候我们可以使用以下几个函数int getsockname(int sockfd,struct sockaddr *localaddr,int *addrlen)int getpeername(int sockfd,struct sockaddr *peeraddr, int *addrlen)struct servent *getservbyname(const char *servname,const char *protoname) struct servent *getservbyport(int port,const char *protoname)struct servent{char *s_name; /* 正式服务名*/char **s_aliases; /* 别名列表*/int s_port; /* 端口号*/char *s_proto; /* 使用的协议*/}一般我们很少用这几个函数.对应客户端,当我们要得到连接的端口号时在connect调用成功后使用可得到系统分配的端口号.对于服务端,我们用INADDR_ANY填充后,为了得到连接的IP我们可以在accept调用成功后使用而得到IP地址.在网络上有许多的默认端口和服务,比如端口21对ftp80对应WWW.为了得到指定的端口号的服务我们可以调用第四个函数,相反为了得到端口号可以调用第三个函数.3.5 一个例子#include <netdb.h>;#include <stdio.h>;#include <stdlib.h>;#include <sys/socket.h>;#include <netinet/in.h>;int main(int argc ,char **argv){struct sockaddr_in addr;struct hostent *host;char **alias;if(argc<2){fprintf(stderr,"Usage:%s hostname|ip..\n\a",argv[0]); exit(1);}argv++;for(;*argv!=NULL;argv++){/* 这里我们假设是IP*/if(inet_aton(*argv,&addr.sin_addr)!=0){host=gethostbyaddr((char *)&addr.sin_addr,4,AF_INET); printf("Address information of Ip %s\n",*argv);}else{/* 失败,难道是域名?*/host=gethostbyname(*argv); printf("Address information of host %s\n",*argv);}if(host==NULL){/* 都不是,算了不找了*/fprintf(stderr,"No address information of %s\n",*argv); continue;}printf("Official host name %s\n",host->;h_name);printf("Name aliases:");for(alias=host->;h_aliases;*alias!=NULL;alias++)printf("%s ,",*alias);printf("\nIp address:");for(alias=host->;h_addr_list;*alias!=NULL;alias++)printf("%s ,",inet_ntoa(*(struct in_addr *)(*alias)));}}在这个例子里面,为了判断用户输入的是IP还是域名我们调用了两个函数,第一次我们假设输入的是IP所以调用inet_aton, 失败的时候,再调用gethostbyname而得到信息.4. 完整的读写函数一旦我们建立了连接,我们的下一步就是进行通信了.在unix下面把我们前面建立的通道看成是文件描述符,这样服务器端和客户端进行通信时候,只要往文件描述符里面读写东西了. 就象我们往文件读写一样.4.1 写函数writessize_t write(int fd,const void *buf,size_t nbytes)write函数将buf中的nbytes字节内容写入文件描述符fd.成功时返回写的字节数.失败时返回-1. 并设置errno变量. 在网络程序中,当我们向套接字文件描述符写时有俩种可能.1)write的返回值大于0,表示写了部分或者是全部的数据.2)返回的值小于0,此时出现了错误.我们要根据错误类型来处理.如果错误为EINTR表示在写的时候出现了中断错误.如果为EPIPE表示网络连接出现了问题(对方已经关闭了连接).为了处理以上的情况,我们自己编写一个写函数来处理这几种情况.int my_write(int fd,void *buffer,int length){int bytes_left;int written_bytes;char *ptr;ptr=buffer;bytes_left=length;while(bytes_left>;0){/* 开始写*/written_bytes=write(fd,ptr,bytes_left);if(written_bytes<=0) /* 出错了*/{if(errno==EINTR) /* 中断错误我们继续写*/written_bytes=0;else /* 其他错误没有办法,只好撤退了*/return(-1);}bytes_left-=written_bytes;ptr+=written_bytes; /* 从剩下的地方继续写*/}return(0);}4.2 读函数readssize_t read(int fd,void *buf,size_t nbyte) read函数是负责从fd中读取内容.当读成功时,read返回实际所读的字节数,如果返回的值是0 表示已经读到文件的结束了,小于0表示出现了错误.如果错误为EINTR说明读是由中断引起的, 如果是ECONNREST表示网络连接出了问题. 和上面一样,我们也写一个自己的读函数.int my_read(int fd,void *buffer,int length) {int bytes_left;int bytes_read;char *ptr;bytes_left=length;while(bytes_left>;0){bytes_read=read(fd,ptr,bytes_read);if(bytes_read<0){if(errno==EINTR)bytes_read=0;elsereturn(-1);}else if(bytes_read==0)break;bytes_left-=bytes_read;ptr+=bytes_read;}return(length-bytes_left);}4.3 数据的传递有了上面的两个函数,我们就可以向客户端或者是服务端传递数据了.比如我们要传递一个结构.可以使用如下方式/* 客户端向服务端写*/struct my_struct my_struct_client;write(fd,(void *)&my_struct_client,sizeof(struct my_struct);/* 服务端的读*/char buffer[sizeof(struct my_struct)];struct *my_struct_server;read(fd,(void *)buffer,sizeof(struct my_struct));my_struct_server=(struct my_struct *)buffer;在网络上传递数据时我们一般都是把数据转化为char类型的数据传递.接收的时候也是一样的注意的是我们没有必要在网络上传递指针(因为传递指针是没有任何意义的,我们必须传递指针所指向的内容)5. 用户数据报发送我们前面已经学习网络程序的一个很大的部分,由这个部分的知识,我们实际上可以写出大部分的基于TCP协议的网络程序了.现在在unix下的大部分程序都是用我们上面所学的知识来写的.我们可以去找一些源程序来参考一下.这一章,我们简单的学习一下基于UDP协议的网络程序.5.1 两个常用的函数int recvfrom(int sockfd,void *buf,int len,unsigned int flags,struct sockaddr * from int *fromlen)int sendto(int sockfd,const void *msg,int len,unsigned int flags,struct sockaddr *to int tolen)sockfd,buf,len的意义和read,write一样,分别表示套接字描述符,发送或接收的缓冲区及大小.recvfrom负责从sockfd接收数据,如果from不是NULL,那么在from里面存储了信息来源的情况,如果对信息的来源不感兴趣,可以将from和fromlen设置为NULL.sendto负责向to发送信息.此时在to里面存储了收信息方的详细资料.5.2 一个实例/* 服务端程序server.c */#include <sys/types.h>;#include <sys/socket.h>;#include <netinet/in.h>;#include <stdio.h>;#include <errno.h>;#define SERVER_PORT 8888#define MAX_MSG_SIZE 1024void udps_respon(int sockfd){struct sockaddr_in addr;int addrlen,n;char msg[MAX_MSG_SIZE];while(1){ /* 从网络上度,写到网络上面去*/n=recvfrom(sockfd,msg,MAX_MSG_SIZE,0, (struct sockaddr*)&addr,&addrlen);msg[n]=0;/* 显示服务端已经收到了信息*/fprintf(stdout,"I have received %s",msg);sendto(sockfd,msg,n,0,(struct sockaddr*)&addr,addrlen);}}int main(void){int sockfd;struct sockaddr_in addr;sockfd=socket(AF_INET,SOCK_DGRAM,0);if(sockfd<0){fprintf(stderr,"Socket Error:%s\n",strerror(errno));exit(1);}bzero(&addr,sizeof(struct sockaddr_in));addr.sin_family=AF_INET;addr.sin_addr.s_addr=htonl(INADDR_ANY);addr.sin_port=htons(SERVER_PORT);if(bind(sockfd,(struct sockaddr *)&ddr,sizeof(struct sockaddr_in))<0) {fprintf(stderr,"Bind Error:%s\n",strerror(errno));exit(1);}udps_respon(sockfd);close(sockfd);}/* 客户端程序*/#include <sys/types.h>;#include <sys/socket.h>;#include <netinet/in.h>;#include <errno.h>;#include <stdio.h>;#include <unistd.h>;#define MAX_BUF_SIZE 1024void udpc_requ(int sockfd,const struct sockaddr_in *addr,int len) {char buffer[MAX_BUF_SIZE];int n;while(1){ /* 从键盘读入,写到服务端*/fgets(buffer,MAX_BUF_SIZE,stdin);sendto(sockfd,buffer,strlen(buffer),0,addr,len);bzero(buffer,MAX_BUF_SIZE);/* 从网络上读,写到屏幕上*/n=recvfrom(sockfd,buffer,MAX_BUF_SIZE,0,NULL,NULL); buffer[n]=0;fputs(buffer,stdout);}}int main(int argc,char **argv){int sockfd,port;struct sockaddr_in addr;if(argc!=3){fprintf(stderr,"Usage:%s server_ip server_port\n",argv[0]); exit(1);}if((port=atoi(argv[2]))<0){fprintf(stderr,"Usage:%s server_ip server_port\n",argv[0]); exit(1);}sockfd=socket(AF_INET,SOCK_DGRAM,0);if(sockfd<0){fprintf(stderr,"Socket Error:%s\n",strerror(errno));exit(1);}/* 填充服务端的资料*/bzero(&addr,sizeof(struct sockaddr_in));addr.sin_family=AF_INET;addr.sin_port=htons(port);if(inet_aton(argv[1],&addr.sin_addr)<0){fprintf(stderr,"Ip error:%s\n",strerror(errno));exit(1);}udpc_requ(sockfd,&addr,sizeof(struct sockaddr_in)); close(sockfd);}########### 编译文件Makefile ##########all:server clientserver:server.cgcc -o server server.cclient:client.cgcc -o client client.cclean:rm -f serverrm -f clientrm -f core上面的实例如果大家编译运行的话,会发现一个小问题的. 在我机器上面,我先运行服务端,然后运行客户端.在客户端输入信息,发送到服务端, 在服务端显示已经收到信息,但是客户端没有反映.再运行一个客户端,向服务端发出信息却可以得到反应.我想可能是第一个客户端已经阻塞了.如果谁知道怎么解决的话,请告诉我,谢谢. 由于UDP协议是不保证可靠接收数据的要求,所以我们在发送信息的时候,系统并不能够保证我们发出的信息都正确无误的到达目的地.一般的来说我们在编写网络程序的时候都是选用TCP协议的.6. 高级套接字函数在前面的几个部分里面,我们已经学会了怎么样从网络上读写信息了.前面的一些函数(read,write)是网络程序里面最基本的函数.也是最原始的通信函数.在这一章里面,我们一起来学习网络通信的高级函数.这一章我们学习另外几个读写函数.6.1 recv和sendrecv和send函数提供了和read和write差不多的功能.不过它们提供了第四个参数来控制读写操作.int recv(int sockfd,void *buf,int len,int flags)int send(int sockfd,void *buf,int len,int flags)前面的三个参数和read,write一样,第四个参数可以是0或者是以下的组合_______________________________________________________________| MSG_DONTROUTE | 不查找路由表|| MSG_OOB | 接受或者发送带外数据|| MSG_PEEK | 查看数据,并不从系统缓冲区移走数据|| MSG_WAITALL | 等待所有数据||---------------------------------------------------------------|MSG_DONTROUTE:是send函数使用的标志.这个标志告诉IP协议.目的主机在本地网络上面,没有必要查找路由表.这个标志一般用网络诊断和路由程序里面.MSG_OOB:表示可以接收和发送带外的数据.关于带外数据我们以后会解释的.MSG_PEEK:是recv函数的使用标志,表示只是从系统缓冲区中读取内容,而不清楚系统缓冲区的内容.这样下次读的时候,仍然是一样的内容.一般在有多个进程读写数据时可以使用这个标志.MSG_WAITALL是recv函数的使用标志,表示等到所有的信息到达时才返回.使用这个标志的时候recv回一直阻塞,直到指定的条件满足,或者是发生了错误. 1)当读到了指定的字节时,函数正常返回.返回值等于len 2)当读到了文件的结尾时,函数正常返回.返回值小于len 3)当操作发生错误时,返回-1,且设置错误为相应的错误号(errno)如果flags为0,则和read,write一样的操作.还有其它的几个选项,不过我们实际上用的很少,可以查看unix Programmer's Manual得到详细解释.6.2 recvfrom和sendto这两个函数一般用在非套接字的网络程序当中(UDP),我们已经在前面学会了.6.3 recvmsg和sendmsgrecvmsg和sendmsg可以实现前面所有的读写函数的功能.int recvmsg(int sockfd,struct msghdr *msg,int flags)int sendmsg(int sockfd,struct msghdr *msg,int flags)struct msghdr{void *msg_name;int msg_namelen;struct iovec *msg_iov;int msg_iovlen;void *msg_control;int msg_controllen;int msg_flags;}struct iovec{void *iov_base; /* 缓冲区开始的地址*/size_t iov_len; /* 缓冲区的长度*/}msg_name和msg_namelen当套接字是非面向连接时(UDP),它们存储接收和发送方的地址信息.msg_name实际上是一个指向struct sockaddr的指针,msg_name是结构的长度.当套接字是面向连接时,这两个值应设为NULL. msg_iov和msg_iovlen指出接受和发送的缓冲区内容.msg_iov是一个结构指针,msg_iovlen指出这个结构数组的大小. msg_control 和msg_controllen这两个变量是用来接收和发送控制数据时的msg_flags指定接受和发送的操作选项.和recv,send的选项一样6.4 套接字的关闭关闭套接字有两个函数close和shutdown.用close时和我们关闭文件一样.6.5 shutdownint shutdown(int sockfd,int howto)TCP连接是双向的(是可读写的),当我们使用close时,会把读写通道都关闭,有时侯我们希望只关闭一个方向,这个时候我们可以使用shutdown.针对不同的howto,系统回采取不同的关闭方式.howto=0这个时候系统会关闭读通道.但是可以继续往接字描述符写.howto=1关闭写通道,和上面相反,着时候就只可以读了.howto=2关闭读写通道,和close一样在多进程程序里面,如果有几个子进程共享一个套接字时,如果我们使用shutdown, 那么所有的子进程都不能够操作了,这个时候我们只能够使用close来关闭子进程的套接字描述符.7. TCP/IP协议你也许听说过TCP/IP协议,那么你知道到底什么是TCP,什么是IP吗?在这一章里面,我们一起来学习这个目前网络上用最广泛的协议.7.1 网络传输分层如果你考过计算机等级考试,那么你就应该已经知道了网络传输分层这个概念.在网络上,人们为了传输数据时的方便,把网络的传输分为7个层次.分别是:应用层,表示层,会话层,传输层,网络层,数据链路层和物理层.分好了层以后,传输数据时,上一层如果要数据的话,就可以直接向下一层要了,而不必要管数据传输的细节.下一层也只向它的上一层提供数据,而不要去管其它东西了.如果你不想考试,你没有必要去记这些东西的.只要知道是分层的,而且各层的作用不同.7.2 IP协议IP协议是在网络层的协议.它主要完成数据包的发送作用. 下面这个表是IP4的数据包格式0 4 8 16 32--------------------------------------------------|版本|首部长度|服务类型| 数据包总长|--------------------------------------------------| 标识|DF |MF| 碎片偏移|--------------------------------------------------| 生存时间| 协议| 首部较验和|------------------------------------------------| 源IP地址|------------------------------------------------| 目的IP地址|-------------------------------------------------| 选项|================================================= | 数据|-------------------------------------------------下面我们看一看IP的结构定义<netinet/ip.h>;struct ip{#if __BYTE_ORDER == __LITTLE_ENDIANunsigned int ip_hl:4; /* header length */unsigned int ip_v:4; /* version */#endif#if __BYTE_ORDER == __BIG_ENDIANunsigned int ip_v:4; /* version */unsigned int ip_hl:4; /* header length */#endifu_int8_t ip_tos; /* type of service */u_short ip_len; /* total length */u_short ip_id; /* identification */u_short ip_off; /* fragment offset field */#define IP_RF 0x8000 /* reserved fragment flag */#define IP_DF 0x4000 /* dont fragment flag */#define IP_MF 0x2000 /* more fragments flag */#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */u_int8_t ip_ttl; /* time to live */u_int8_t ip_p; /* protocol */u_short ip_sum; /* checksum */struct in_addr ip_src, ip_dst; /* source and dest address */};ip_vIP协议的版本号,这里是4,现在IPV6已经出来了ip_hlIP包首部长度,这个值以4字节为单位.IP协议首部的固定长度为20个字节,如果IP包没有选项,那么这个值为5.ip_tos服务类型,说明提供的优先权.ip_len说明IP数据的长度.以字节为单位.ip_id标识这个IP数据包.ip_off碎片偏移,这和上面ID一起用来重组碎片的.ip_ttl生存时间.没经过一个路由的时候减一,直到为0时被抛弃.ip_p协议,表示创建这个IP数据包的高层协议.如TCP,UDP协议.ip_sum首部校验和,提供对首部数据的校验.ip_src,ip_dst发送者和接收者的IP地址关于IP协议的详细情况,请参考RFC7917.3 ICMP协议ICMP是消息控制协议,也处于网络层.在网络上传递IP数据包时,如果发生了错误,那么就会用ICMP协议来报告错误.ICMP包的结构如下:0 8 16 32---------------------------------------------------------------------| 类型| 代码| 校验和|--------------------------------------------------------------------| 数据| 数据|--------------------------------------------------------------------ICMP在<netinet/ip_icmp.h>;中的定义是struct icmphdr{u_int8_t type; /* message type */u_int8_t code; /* type sub-code */u_int16_t checksum;union{struct{u_int16_t id;u_int16_t sequence;} echo; /* echo datagram */u_int32_t gateway; /* gateway address */struct{u_int16_t __unused;u_int16_t mtu;} frag; /* path mtu discovery */} un;};关于ICMP协议的详细情况可以查看RFC7927.4 UDP协议UDP协议是建立在IP协议基础之上的,用在传输层的协议.UDP和IP协议一样是不可靠的数据报服务.UDP的头格式为:0 16 32---------------------------------------------------| UDP源端口| UDP目的端口|---------------------------------------------------| UDP数据报长度| UDP数据报校验|---------------------------------------------------UDP结构在<netinet/udp.h>;中的定义为:struct udphdr {u_int16_t source;u_int16_t dest;u_int16_t len;u_int16_t check;};关于UDP协议的详细情况,请参考RFC7687.5 TCPTCP协议也是建立在IP协议之上的,不过TCP协议是可靠的.按照顺序发送的.TCP的数据结构比前面的结构都要复杂.0 4 8 10 16 24 32-------------------------------------------------------------------| 源端口| 目的端口|-------------------------------------------------------------------| 序列号|------------------------------------------------------------------| 确认号|------------------------------------------------------------------| | |U|A|P|S|F| ||首部长度| 保留|R|C|S|Y|I| 窗口|| | |G|K|H|N|N| |-----------------------------------------------------------------| 校验和| 紧急指针|-----------------------------------------------------------------| 选项| 填充字节|-----------------------------------------------------------------TCP的结构在<netinet/tcp.h>;中定义为:struct tcphdr{u_int16_t source;u_int16_t dest;u_int32_t seq;u_int32_t ack_seq;#if __BYTE_ORDER == __LITTLE_ENDIANu_int16_t res1:4;u_int16_t doff:4;u_int16_t fin:1;u_int16_t syn:1;u_int16_t rst:1;u_int16_t psh:1;u_int16_t ack:1;u_int16_t urg:1;u_int16_t res2:2;#elif __BYTE_ORDER == __BIG_ENDIANu_int16_t doff:4;u_int16_t res1:4;u_int16_t res2:2;u_int16_t urg:1;u_int16_t ack:1;u_int16_t psh:1;u_int16_t rst:1;u_int16_t syn:1;u_int16_t fin:1;#endifu_int16_t window;u_int16_t check;u_int16_t urg_prt;};source发送TCP数据的源端口dest接受TCP数据的目的端口seq标识该TCP所包含的数据字节的开始序列号ack_seq确认序列号,表示接受方下一次接受的数据序列号.doff数据首部长度.和IP协议一样,以4字节为单位.一般的时候为5urg如果设置紧急数据指针,则该位为1ack如果确认号正确,那么为1psh如果设置为1,那么接收方收到数据后,立即交给上一层程序rst为1的时候,表示请求重新连接syn为1的时候,表示请求建立连接fin为1的时候,表示亲戚关闭连接window窗口,告诉接收者可以接收的大小check对TCP数据进行较核urg_ptr如果urg=1,那么指出紧急数据对于历史数据开始的序列号的偏移值关于TCP协议的详细情况,请查看RFC7937.6 TCP连接的建立TCP协议是一种可靠的连接,为了保证连接的可靠性,TCP的连接要分为几个步骤.我们把这个连接过程称为"三次握手".下面我们从一个实例来分析建立连接的过程.第一步客户机向服务器发送一个TCP数据包,表示请求建立连接. 为此,客户端将数据包的SYN位设置为1,并且设置序列号seq=1000(我们假设为1000).第二步服务器收到了数据包,并从SYN位为1知道这是一个建立请求的连接.于是服务器也向客户端发送一个TCP数据包.因为是响应客户机的请求,于是服务器设置ACK为1,sak_seq=1001(1000+1)同时设置自己的序列号.seq=2000(我们假设为2000).第三步客户机收到了服务器的TCP,并从ACK为1和ack_seq=1001知道是从服务器来的确认信息.于是客户机也向服务器发送确认信息.客户机设置ACK=1,和ack_seq=2001,seq=1001,发送给服务器.至此客户端完成连接.最后一步服务器受到确认信息,也完成连接.通过上面几个步骤,一个TCP连接就建立了.当然在建立过程中可能出现错误,不过TCP协议可以保证自己去处理错误的.说一说其中的一种错误.听说过DOS吗?(可不是操作系统啊).今年春节的时候,美国的五大网站一起受到攻击.攻击者用的就是DOS(拒绝式服务)方式.概括的说一下原理.客户机先进行第一个步骤.服务器收到后,进行第二个步骤.按照正常的TCP连接,客户机应该进行第三个步骤.不过攻击者实际上并不进行第三个步骤.因为客户端在进行第一个步骤的时候,修改了自己的IP地址,就是说将一个实际上不存在的IP填充在自己IP数据包的发送者的IP一栏.这样因为服务器发的IP地址没有人接收,所以服务端会收不到第三个步骤的确认信号,这样服务务端会在那边一直等待,直到超时.这样当有大量的客户发出请求后,服务端会有大量等待,直到所有的资源被用光,而不能再接收客户机的请求.这样当正常的用户向服务器发出请求时,由于没有了资源而不能成功.于是就出现了春节时所出现的情况.8. 套接字选项有时候我们要控制套接字的行为(如修改缓冲区的大小),这个时候我们就要控制套接字的选项了.8.1 getsockopt和setsockopt。
UNIX操作系统命令大全
精心整理UNIX 系统操作命令大全UNIX 系统操作命令第一章登录和退出用户在登录前,首先要向系统管理员申请一个用户注册名,不论用户从哪台计算机登录到ITPNET 上都将访问相同的文件系统。
1.1登录sun%注:[hide]1.2退出[Ctrl-D]Login :1.3update 等待话xargs第二章目录操作命令2.1显示目录命令:pwd (printworkingdirectory )格式:pwd功能:显示出用户当前工作目录的全路径名。
例如:%pwd2.2建立目录命令:mkdir (makedirectory )格式:mkdirdirectory_name功能:建立新目录例如:%mkdirdirectory2.3改变目录命令:cd(changedirectory)格式:cddirectory_name功能:改变当前工作目录注释:目录名选项有:?(1)目录名,转到当前目录下的子目录。
?(2)..表示转到当前目录的父目录。
?(3)/表示转到根目录。
?(4)没有选项时,转到用户的主目录。
例如:%cddirectory2.4命令:格式:注释:?(1)?(2)例如:3.1命令:格式:??选项:-a??-l?????-r??-g??-t例如:3.2命令:格式:catfilename功能:显示出文件的内容。
注释:当文件内容在屏幕上滚动显示时,可按Ctrl+S键屏幕滚暂停,按Ctrl+Q ??键继续显示。
例如:%catfilename3.3按屏幕显示文件内容命令:more格式:morefilename功能:按屏幕一屏一屏显示出文件内容选项:注释:在屏幕显示过程中有功能键。
空格键继续下一屏的输出;回车键看下??一行的输出;q键跳出more状态;/字符串查旬字符串所在处;a键返??回到上一屏。
例如:%morefilename3.4分页显示文件内容命令:pg(page)格式:pg[option]filename功能:分页显示指定文件的内容。
常用系统函数表
常用系统函数表目录1. 缓冲区操作函数 02. 字符分类函数 (1)3. 数据转换函数 (3)4. 目录控制函数 (6)5. 文件处理函数 (7)C.5.1 如下函数在一个文件句柄指定的文件上操作 (7)C.5.2如下函数在一个路径或文件名指定的文件上操作 (8)6. 数学函数 (11)7. 输入和输出函数 (17)C.7.1 流I/O函数 (17)C.7.2 低级I/O函数 (26)C.7.3 控制台和端口I/O函数 (29)8. 进程控制函数 (31)9. 查找和分类函数 (32)10. 字符串操作函数 (33)这里只收录了一些VC++6.0变异环境支持的常用的函数,使用不同的编译系统需参考编译系统的文档。
1. 缓冲区操作函数函数名:_memccpy函数原型:void *_memccpy(void *dest,const void *src,int c,unsigned int count);参数:dest 目的指针;src 源指针;c 拷贝的最后字符;count 字符个数。
所需头文件:<memory.h>或<string.h>功能:从src所指向的地址开始拷贝0个或多个字节到dest中。
当指定字符c已拷贝或已拷贝count个字节后停止。
返回值:如果字符c被拷贝,返回dest中该字符直接后继字节的指针。
如果c没有被拷贝,则返回NULL。
函数名:memchr函数原型:void *memchr (const void *buf,int c,sizet counr);参数:buf 缓冲区的指针;c 查找的字符;count检查的字符个数。
所需头文件:<memory.h>或<string.h>功能:查找buf的前count个字节中c的第一次出现,当找到c或已检查完count个字节时停止。
返回值:如果成功,返回buf中c首次出现的位置的指针;否则返回NULL。
getopt函数
getopt函数
getopt函数是UNIX系统中最常用的命令行参数解析函数,它帮助程序员从命令行获取参数,可以使用这些参数来控制程序的运行和设置。
在C/C++等常用语言中都有标准库可以使用,而getopt函数
是其中最重要的一部分,可用于处理复杂的命令行参数解析,例如long argument。
getopt函数主要用于处理以“-”开头的参数,这些参数统称为“选项”,也可以称为“键/值”,常见的参数形式有“-h”或“--help”,“-v”或“--version”等。
当你的程序比较复杂时,getopt函数可以帮助你准确的解析出形式。
getopt函数也支持选项后面跟参数的形式,这样可以传递更多
的信息给程序。
比如“-o <file>”表示程序要把输出结果输出到<file>文件中,另外“--name <value>”表示程序以<value>为名字来运行,这些参数可以指定程序运行的具体模式以及在运行中要处理哪类信息。
此外,getopt函数还可以帮助你展示参数的使用方法,例如“-v”或者“--version”参数可以把程序的版本号显示出来;“-h”或“--help”可以显示出程序使用方法,这样用户就可以更加了解你的程序了。
最后,getopt函数还支持结合的参数,比如“-vx”或“-xv”,这样用户在输入参数的时候只需要输入一次即可,而不必输入两次,大大提高了使用者的体验。
getopt函数可以说是UNIX命令行参数解析中不可或缺的重要函
数,它可以极大提高命令行参数解析的灵活性和可用性,它的出现给UNIX程序的开发者提供了更大的的灵活性和可能性,而且它的使用也比较容易,就可以大大提高UNIX程序的可用性。
tcflush函数
tcflush函数tcflush函数是一个被广泛使用的unix操作系统函数,它用于清除与指定终端关联的输入和输出缓冲区。
由POSIX定义,它可以用于控制目标终端(终端控制器)上的输入和输出操作,并且在大多数操作系统和程序语言中都可以使用。
尽管tcflush函数的原理很容易理解,但如何正确使用该函数仍然是一个困扰许多UNIX系统程序员的问题。
因此,了解tcflush函数具体的用法以及如何有效利用它是非常重要的。
在本文中,我们将对tcflush函数的操作原理、完成及实例进行详细介绍。
1.tcflush函数操作原理tcflush函数的作用是清空与指定终端关联的输入和输出缓冲区。
它可以用于终端控制,包括目标终端上的标准输入(stdin)和标准输出(stdout)。
tcflush函数的基本操作原理比较简单。
首先,该函数会检测与指定终端的连接状态,最终去决定是否需要将该终端的缓冲清除。
如果终端连接正常,tcflush函数将删除其缓冲中所有数据,包括输入输出数据及缓冲设置。
最后,tcflush函数还会更新终端的状态位,以确保终端上的输入和输出都能正常进行。
2.tcflush函数的完成tcflush函数的完成比较简单,但仍需要一些准备工作,包括:(1)确定要清除的终端在调用tcflush函数之前,必须先确定要清除的终端。
一般来说,tcflush函数可以操作串口,终端,串口和终端的结合体等各种终端。
(2)获取终端的文件描述符在调用tcflush函数之前,必须获取与指定终端相关联的文件描述符。
一般通过调用open函数或文件描述符查找函数获得。
(3)调用tcflush函数当准备工作完成后,即可调用tcflush函数开始清除终端的缓冲。
该函数主要包括两个参数:文件描述符和清除类型。
3. tcflush函数实例下面以C语言为例,结合实例,来看看如何调用tcflush函数: #include<termios.h>//打开与指定终端的连接int fd = open(/dev/ttyUSB0 O_RDWR | O_NOCTTY);//调用tcflush函数,清除输入和输出缓冲int ret = tcflush(fd, TCIOFLUSH);在上面的例子中,tcflush函数的第一个参数为文件描述符,第二个参数为清除类型,该参数指定要清除终端的输入或输出缓冲。
trap函数
trap函数
trap函数是Unix/Linux操作系统的一个内置命令,用于捕获和处理Shell脚本中的信号。
信号是一个在Unix系统中发送给进程的特殊事件,用于通知进程发生了某种事件,例如软件错误、用户输入等。
trap函数
可以设置Shell脚本在接收到信号时的操作,例如执行指定的命令或函数。
trap函数语法为:
```。
```。
- INT:中断信号,通常是用户在Shell脚本运行时按下Ctrl+C触发的。
-TERM:终止信号,用于请求进程优雅地终止。
- EXIT:退出信号,在Shell脚本结束时自动发送。
例如,下面的代码可以在Shell脚本运行时捕获INT信号,执行指定
的命令:
```。
trap 'echo "CTRL+C被按下,程序即将退出"' INT。
```。
当用户在Shell脚本运行时按下Ctrl+C,将会触发执行`echo "CTRL+C被按下,程序即将退出"`这个命令。
ftok函数
ftok函数
ftok函数是Unix系统中提供的一种比较重要的进程间通信机制,它有助于通过编程实现多个进程之间的同步和共享。
在Unix系统中,ftok函数可以将一个文件路径和一个整数标识转换成一个系统全局唯一的IPC(进程间通信)标识码。
ftok函数可以实现多个进程间的通信。
它的操作类似于一个系统的唯一标识码,可以将不同的进程间的消息传递给对方,从而实现通信。
借助ftok函数,程序可以从不同的进程中接收或发送消息。
ftok函数有两个参数,第一个参数是文件路径,第二个参数是一个不超过8个字节的整数,可以是任何整数值,用来标识文件。
结合这两个参数,ftok函数会返回一个唯一的key,可用来标识文件。
在Unix系统中,ftok函数是一种重要的进程间通信机制,它有助于实现不同进程间的同步和共享。
这个函数有助于实现进程间的消息传递,从而实现同步和通信。
它的参数是文件路径和一个整数,可以将他们转换成一个系统全局唯一的IPC标识码。
INFORMIX函数大全
目录INFORMIX数据类型 (2)表达式用途 (3)表达式 (4)校正表达式 (4)条件表达式 (4)一般性CASE表达式 (4)线形CASE表达式 (5)常量表达式 (5)引号字符串表达式 (6)函数清单 (6)ABS函数 (9)DBINFO函数 (10)CARDINALITY函数 (14)长度函数 (14)DA TE函数 (15)DAY函数 (15)三角函数 (16)ACOS函数 (16)ASIN函数 (16)ATAN函数 (16)ATAN2函数 (16)COUNT函数 (17)COUNT(*)函数 (17)COUNT DISTINCT和COUNT UNIQUE函数 (17)A VG函数 (18)USER函数 (18)DBSERVERNAME 和SITENAME函数 (18)TODAY函数 (18)CURRENT函数 (18)DA TETIME (19)COLUMN (19)Concatonation 运算符 (19)DECODE函数 (19)EXP函数 (20)EXTEND函数 (20)FILETOBLOB函数和FILETOCLOB函数 (21)HEX函数 (22)IFX_ALLOW_NEWLINE函数 (22)IPX_REPLACE_MODULE函数 (22)INITCAP函数 (23)LOCOPY函数 (23)LOGN函数 (24)LOGN10函数 (24)LOTOFILE函数 (25)LOWER函数 (26)LPAD(源字符串,长度,嵌入字符串) (26)RPAD(源字符串,长度,嵌入字符串) (26)MAX(数字列|数字表达式) (26)MIN(数字列|数字表达式) (26)MDY(expr1,expr2,expr3) (26)MOD(被除数,除数) (26)MONTH(date/dtime_expr) (26)NVL(表达式1,表达式2) (27)OCTET_LENGTH(变量名|列命) (27)POW(底数,指数) (27)RANGE(数字列|数字表达式) (27)REPLACE(源字符串,匹配字符串,新字符串) (27)ROOT(被开方数,指数) (27)ROUND(数字表达式,圆整系数) (27)SIN(弧度) (27)SITENAME (27)STDEV(数字列) (27)SUBSTR(源字符串,开始位置,长度) (27)SUM(数字列|数字表达式) (28)TAN(弧度) (28)TO_CHAR(DA TE|DA TETIME,格式字符串) (28)TO_DATE(字符表达式,格式字符串) (28)TODAY (28)TRIM([LEADING|TRAILING|BOTH] trim_expr FROM source_expr) (28)TRUNC(表达式,截去系数) (29)UPPER(源字符串) (29)V ARIANCE(数字列) (29)WEEKDAY(date|dtime_expr) (29)YEAR(date|dtime_expr) (29)INFORMIX数据类型表达式用途表达式校正表达式CAST(表达式::target_data_type AS target_data_type)可以用CAST AS关键字或双冒号校正操作符(::)将一种数据类型的表达式校正为另一种数据类型的表达式。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
UNIX常用系统函数getopt(分析命令行参数)相关函数表头文件 #include<unistd.h>定义函数 int getopt(int argc,char * const argv[ ],const char * optstring);函数说明 getopt()用来分析命令行参数。
参数argc和argv是由main()传递的参数个数和内容。
参数optstring 则代表欲处理的选项字符串。
此函数会返回在argv 中下一个的选项字母,此字母会对应参数optstring 中的字母。
如果选项字符串里的字母后接着冒号":",则表示还有相关的参数,全域变量optarg 即会指向此额外参数。
如果getopt()找不到符合的参数则会印出错信息,并将全域变量optopt设为""字符,如果不希望getopt()印出错信息,则只要将全域变量opterr设为0即可。
返回值如果找到符合的参数则返回此参数字母,如果参数不包含在参数optstring 的选项字母则返回""字符,分析结束则返回-1。
范例 #include<stdio.h>#include<unistd.h>int main(int argc,char **argv){int ch;opterr = 0;while((ch = getopt(argc,argv,"a:bcde"))!= -1)switch(ch){case 'a':printf("option a:'%s'\n",optarg);break;case 'b':printf("option b :b\n");break;default:printf("other option :%c\n",ch);}printf("optopt +%c\n",optopt);}执行 $./getopt –boption b:b$./getopt –cother option:c$./getopt –aother option :$./getopt –a12345 option a:'12345'isatty(判断文件描述词是否是为终端机)相关函数 ttyname表头文件 #include<unistd.h>定义函数 int isatty(int desc);函数说明如果参数desc所代表的文件描述词为一终端机则返回1,否则返回0。
返回值如果文件为终端机则返回1,否则返回0。
范例参考ttyname()。
select(I/O多工机制)表头文件 #include<sys/time.h>#include<sys/types.h>#include<unistd.h>定义函数 int select(int n,fd_set * readfds,fd_set * writefds,fd_set * exceptfds,struct timeval * timeout);函数说明 select()用来等待文件描述词状态的改变。
参数n代表最大的文件描述词加1,参数readfds、writefds 和exceptfds 称为描述词组,是用来回传该描述词的读,写或例外的状况。
底下的宏提供了处理这三种描述词组的方式:FD_CLR(inr fd,fd_set* set);用来清除描述词组set中相关fd 的位FD_ISSET(int fd,fd_set *set);用来测试描述词组set中相关fd 的位是否为真FD_SET(int fd,fd_set*set);用来设置描述词组set中相关fd的位FD_ZERO(fd_set *set);用来清除描述词组set的全部位参数 timeout为结构timeval,用来设置select()的等待时间,其结构定义如下struct timeval{time_t tv_sec;time_t tv_usec;};返回值如果参数timeout设为NULL则表示select()没有timeout。
错误代码执行成功则返回文件描述词状态已改变的个数,如果返回0代表在描述词状态改变前已超过timeout时间,当有错误发生时则返回-1,错误原因存于errno,此时参数readfds,writefds,exceptfds 和timeout的值变成不可预测。
EBADF 文件描述词为无效的或该文件已关闭EINTR 此调用被信号所中断EINVAL 参数n 为负值。
ENOMEM 核心内存不足范例常见的程序片段:fs_set readset;FD_ZERO(&readset);FD_SET(fd,&readset);select(fd+1,&readset,NULL,NULL,NULL);if(FD_ISSET(fd,readset){……}ttyname(返回一终端机名称)相关函数 Isatty表头文件 #include<unistd.h>定义函数 char * ttyname(int desc);函数说明如果参数desc所代表的文件描述词为一终端机,则会将此终端机名称由一字符串指针返回,否则返回NULL。
返回值如果成功则返回指向终端机名称的字符串指针,有错误情况发生时则返回NULL。
范例 #include<unistd.h>#include<sys/types.h>#include <sys/stat.h>#include<fcntl.h>main(){int fd;char * file = "/dev/tty";fd = open (fiel,O_RDONLY);printf("%s",file);if(isatty(fd)){printf("is a tty.\n");printf("ttyname = %s \n",ttyname(fd)); }else printf(" is not a tty\n");close(fd);}执行 /dev/tty is a ttyttyname = /dev/tty添加评论 | 阅读评论 (1)3:45 | 固定链接 | 引用通告 (0) | 记录它固定链接关闭/~yhf/linux_c/function/15.htmlgetenv(取得环境变量内容)相关函数 putenv,setenv,unsetenv表头文件 #include<stdlib.h>定义函数 char * getenv(const char *name);函数说明 getenv()用来取得参数name环境变量的内容。
参数name为环境变量的名称,如果该变量存在则会返回指向该内容的指针。
环境变量的格式为name=value。
返回值执行成功则返回指向该内容的指针,找不到符合的环境变量名称则返回NULL。
范例 #include<stdlib.h>mian(){char *p;if((p = getenv("USER")))printf("USER=%s\n",p);}执行 USER = rootputenv(改变或增加环境变量)相关函数 getenv,setenv,unsetenv表头文件 #include4<stdlib.h>定义函数 int putenv(const char * string);函数说明 putenv()用来改变或增加环境变量的内容。
参数string的格式为name=value,如果该环境变量原先存在,则变量内容会依参数string改变,否则此参数内容会成为新的环境变量。
返回值执行成功则返回0,有错误发生则返回-1。
错误代码 ENOMEM 内存不足,无法配置新的环境变量空间。
范例 #include<stdlib.h>main(){char *p;if((p = getenv("USER")))printf("USER =%s\n",p);putenv("USER=test");printf("USER+5s\n",getenv("USER"));}执行 USER=rootUSER=rootsetenv(改变或增加环境变量)相关函数 getenv,putenv,unsetenv表头文件 #include<stdlib.h>定义函数 int setenv(const char *name,const char * value,int overwrite);函数说明 setenv()用来改变或增加环境变量的内容。
参数name为环境变量名称字符串。
参数 value则为变量内容,参数overwrite用来决定是否要改变已存在的环境变量。
如果overwrite不为0,而该环境变量原已有内容,则原内容会被改为参数value所指的变量内容。
如果overwrite为0,且该环境变量已有内容,则参数value会被忽略。
返回值执行成功则返回0,有错误发生时返回-1。
错误代码 ENOMEM 内存不足,无法配置新的环境变量空间范例 #include<stdlib.h>main(){char * p;if((p=getenv("USER")))printf("USER =%s\n",p);setenv("USER","test",1);printf("USER=%s\n",getenv("USEr"));unsetenv("USER");printf("USER=%s\n",getenv("USER"));}执行 USER = rootUSER = testUSER = (null)添加评论3:44 | 固定链接 | 引用通告 (0) | 记录它固定链接关闭/~yhf/linux_c/function/14.htmlaccept(接受socket连线)相关函数 socket,bind,listen,connect表头文件 #include<sys/types.h>#include<sys/socket.h>定义函数 int accept(int s,struct sockaddr * addr,int * addrlen);函数说明 accept()用来接受参数s的socket连线。