Linux C_istream返回文件描述符_弗里曼的小伙伴的博客-程序员宝宝

技术标签: Linux  shell  gcc  linux  

Linux C

2014年3月10日

1  编译和链接

1.1 流程

源程序-》预编译-》编译-》链接-》完成

1)       源程序:书写源程序代码

2)       预编译:宏指令处理,生成编译源程序(-E)

3)       编译:将源程序汇编(-S),然后编译生成目标程序(二进制)(-c)

4)       链接:将目标程序中的库函数链接实体,生成二进制。如果使用的是静态库,则将静态库中的代码copy到目标程序中,生成新的目标程序。如果使用的是动态库,则使用动态库的目录替换(-L)。

参考:

http://www.cnblogs.com/ggjucheng/archive/2011/12/14/2287738.html

 

1.2 宏指令

1.2.1文件包含

#include <>/””:包含库头文件/自定义头文件。

1.2.2条件编译

#if #else #elif #endif

#ifdef #endif #ifndef

1.2.3参数连接#、##

#:将参数转化为字符串,可以与两端的字符串无缝相连。

##:连接。将参数与指定的字符组合。

参考:http://lwj8666.blog.163.com/blog/static/1896693920100142178247/

1.2.4定义

#define fun(arg) realfun(arg):定义

#undef:取消定义

1.2.5错误

#error:停止编译并显示错误。

1.2.6可变参数

…:可变参数。

1.2.7参考

http://hi.baidu.com/ccocwwh/item/e263b729889ff080ae48f554

http://wenku.baidu.com/link?url=TLtFFzO3XpiqeUKU_vRJG8Ta63ox33qqQIlH-uuvxuKBkYluefSsdc0W_qlNSA6iybkspBo4FIHpCKLHMSC1-BsDubMW0wgttOJzmqo7eMW

 

 

2 gcc

2.1 命令

-o:输出文件。

-D:宏定义 –D name=value。

-E:预编译。生成预编译后的源文件。

-S:汇编,生成汇编代码。

-c:编译,生成目标文件。

-L:库,连接库文件,首先选择动态库,如果没有找到,则查找静态库。

-I:头,连接库的头文件。

-static:强制使用静态库。

不使用任何指令,则生成可执行文件。

-std:当前C的标准版本。

多文件编译:直接输入多个文件。

-pedantic:检查错误,检查ANSI C中要求的检查项,不是全部。

-W:警告,-Wall,所有警告;-Werror:将警告当做错误处理,如果抛出警告,则中断执行。

2.2 参考

http://www.linuxidc.com/Linux/2011-03/33406.htm

http://www.cnblogs.com/ggjucheng/archive/2011/12/14/2287738.html

3 静态库

3.1 创建静态库

c-》o-》a

1)   编写C源程序

2)   编译为目标文件.o

3)   打包形成库(文档)文件

3.2 使用静态库

调用-》链接

1)   编辑调用库函数的源代码

2)   编译源代码,链接库函数

a)   使用头文件进行链接

b)   在源文件中直接声明(非标准方法)

3.3 静态库的搜索路径

1)   -L指定的路径

2)   环境变量:LIBRARY_PATH

3)   默认目录:/lib》/usr/lib》/usr/local/lib

注意:如果不指定路径,不会在程序当前路径进行搜索。

4 动态库

4.1 创建动态库

源程序-》编译为位置无关代码(PIC)目标文件》编译为共享的动态库。

1)   源程序:编写功能函数

2)   PIC:编译为PIC格式的目标文件

3)   SO:编译为共享动态库

4.2 使用动态库

源程序(加载动态库)-》源程序(获取动态库函数)-》源程序(调用)-》源程序(关闭动态库)-》编译链接动态库

1)   加载动态库:使用dlopen()加载动态库,并获取其句柄。注意:为了使用与动态库有关的函数,要添加dlfcn.h头文件。

2)   获取服务:通过句柄查找相关的服务函数,并得到函数指针。

3)   使用函数指针调用函数。

4)   关闭动态库句柄。

4.3 动态链接库加载路径

1)   –L指定的路径。

2)   环境变量:LD_LIBRARY_PATH。

3)   动态链接库配置文件:/etc/ld.so.conf。

4)   默认路径:/lib》/usr/lib。

4.4 参考

http://blog.csdn.net/jenshy/article/details/674621

Linux下生成动态链接库是否必须使用 -fPIC 的问题:http://www.linuxidc.com/Linux/2011-06/37268.htm

5 异常处理

信号机制

信号又称为软中断信号,用于通知进程发生了异步事件。对信号处理:指定函数,忽略或调用默认方法(一般为关闭进程)。

进程表的表项中保留了所有可以种类的信号,但每种只保留最后一次状态。

参考:http://www.cnblogs.com/taobataoma/archive/2007/08/30/875743.html

6 文件系统

6.1 概述

6.1.1文件结构

Linux文件系统中所有内容全部映射为文件。

物理设备映射为dev/下的文件,无法直接使用,必须使用mount命令挂载到逻辑系统下。

硬盘的文件系统可以使用多种格式,可以被设置为多个逻辑分区。每个逻辑分区由以下块组成:

超级块:全区数据信息。

i节点表:存储i节点数据,每个inode包含文件的id和指针。

目录表:存储文件名称、目录名称及其对应的i节点指针。

数据块:存储数据。

参考:http://baike.baidu.com/link?url=CUDFC0DlmhIQvcIsX1sUILBZAdVFtf2x1U0hjyKuVOS_ZjlpW0HKNEcmua8Kquzh

6.1.2文件类型

普通文件:数据文件,不包含文件系统信息。

目录文件:包含文件inode和文件名映射信息。

设备文件:硬件映射。

链接文件:快捷方式。

管道文件:IPC进程间交互文件。

6.1.3文件描述符

文件描述符是内核维护的文件的索引值(FILENO)。对文件的使用,使用引用数来决定文件的生存期,如果引用数为0,则删除此文件。

参考:

http://baike.baidu.com/view/1303430.htm?fr=wordsearch

6.2 文件共享

使用scp(securecopy)命令可以在不同的linux系统之间进行文件传输。

从远程服务器下载:

scp –P -r [email protected]:targetPath localPath

向远程服务器上传:

scp –r localPath –P [email protected]:targetPath

参考:

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

http://www.jb51.net/LINUXjishu/70474.html

系统API

6.3 字节序

对于不同的CPU,其字节在内存中的存储顺序可能不同。

小端字节序:低位数据存放在内存中低位,高位数据存放在内存中的高位。

大端字节序:与小端字节序相反,低位数据存放在内存中的高位,高位数据存放在内存中的低位。

Intel X86使用小端字节序,有些平台使用大端字节序。

例如:数据0x0001->内存中0x4001(01)0x4002(00) 小端

                                                                                                Ox4001(00)0x4002(01)大端

7 常用头文件

标准头文件在/usr/include目录下,系统API头文件在/usr/include/sys目录下。使用时标准头文件可能直接引用,系统API要加入sys/*调用。

7.1 变量约定

C标准规定:以_+大写字母或者__开头的变量,为系统或标准库所定义,自定义变量不要使用这种方式。

参考:http://www.16kan.com/question/detail/244107.html

7.2 入口函数

int main(int argc,char *argv[],char *env[]);

程序的入口函数。argc表示程序参数个数。argv:表示参数(执行程序的命令就是第一个参数)。env:表示程序当前的所有环境变量(不用输入,系统自动进行赋值)。

7.3 sys/types.h

基本系统数据类型,包括C标准库中一些类型的实际定义。

参考:http://blog.sina.com.cn/s/blog_7095a51301010hb9.html

7.4 sys/stat.h

文件状态。

参考:

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

7.5 fcntl.h

文件控制。

7.5.1 文件操作

int create(const char *pathname,mode_t mode);

创建文件。成功返回文件描述符(标记输入输出的id,由系统维护参考:http://blog.sina.com.cn/s/blog_8e48f19a01013lrb.html),失败返回-1

内部调用 open()。

int open(const char *pathname,mode_t mode);

打开文件。成功返回文件描述符,失败返回-1。

int close(int iStream);

关闭文件。成功返回0,失败返回-1。

int unlink(int iStream);

删除文件(引用数-1,只有引用数减为0时才真正删除)。成功返回0,失败返回-1。

7.5.2 文件读写

size_t read(int iStream,void *buf,size_t count);

从iStream中读取count个字符到buf中。成功返回实际读取的字符数,失败返回-1。

size_t write(int iStream,const void *buf,size_tcount);

从buf中读取count个字符写入到iStream文件中。成功返回实际写入的字符数,失败返回-1。

off_t lseek(int iStream,off_t offset,int whence);

随机读取。设置iSteam当前的读写位置为whence+offset。

成功返回设置后的读写位置。失败返回-1。

参考:

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

7.6 unistd.h

linux下的posix标准头文件。用于进行系统API调用。

7.6.1文件属性操作

int chown(const char *path,uid_t uid,gid_t gid);

修改文件的所有者信息。成功返回0,失败返回-1。

对应shell的chown命令。

int fchown(int iStream,uid_t uid,gid_t gid);

chown的流操作版本。

int lchown(const char *path,uid_t uid,gid_t gid);

修改符号连接的所有者信息。成功返回0,失败返回-1。

int chmod(const char *path,mode_t mode);

修改文件权限信息。成功返回0,失败返回-1。

对应shell的chmod命令。

int fchmod(int iStream,mode_t mode);

chmod的流操作版本。

mode_t umask(mode_t mode);

设置mode掩码(其后的文件不再具有此属性),返回之前的权限。

int access(const char *path,mode_t mode);

检查path文件的mode权限。成功返回0,失败返回-1。

7.6.2进程操作

7.6.2.1  进程属性

_pid_t getpid(void);

获取当前的进程id。成功返回id,失败返回-1。

_pid_t getppid(void);

获取进程的父进程id。成功返回id,失败返回-1。

_pid_t getpgrp(void);

返回进程组ID。成功返回id,失败返回-1。

int setpgid(_pid_t pid,_pid_t pgid);

设置进程组ID。使用0则指定为当前进程id。成功返回0,失败返回-1。

_uid_t getuid(void);

返回进程运行的用户id。成功返回id,失败返回-1。

_uid_t geteuid(void);

返回进程运行期间有效的用户id。成功返回id,失败返回-1。

_gid_t getgid(void);

获取进程运行用户的组id。成功返回id,失败返回-1。

_gid_t getegid(void);

获取进行运行期间有效的组id。成功返回id,失败返回-1。

_pid_t getsid(_pid_t pid);

获取当前会话id。成功返回id,失败返回-1。

_pid_t setsid(void);

生成新的会话,新会话以产生会话的进程为首进程。成功返回首进程id,失败返回-1。

7.6.2.2  创建进程

1)       fork

int fork(void);

创建子进程。子进程会复制父进程的所有数据,然后运行,但与父进程并不共享数据。

如果成功创建,子进程执行,fork()在子进程返回0;子进程结束后,父进程执行,fork()在父进程中返回子进程的id。如果失败返回-1。

注意:父进程与子进程的执行次序是不固定的。

2)       exec

int execl(const char *file,const char *arg,…,NULL);

int execle(const char *file,const char *arg,…,NULL,char *env[]);

int execlp(const char *file,const char *arg,…,NULL);

int execlpe(const char *file,const char *arg,…,NULL,char *env[]);

int execv(const char *file,const char *arg[]);

int execve(const char *file,const char *arg[],char*env[]);

int execvp(const char *file,const char *arg[]);

int execvpe(const char *file,const char *arg[],char*env[]);

创建进程,并替换父进程。file是要执行的文件名。

区别:

execl表示参数为列表,最后要有个NULL参数表示结束。file为绝对或相对路径。

execv表示参数为vector,最后也要有个NULL参数表示结束。

execlp/exelvp表示file这PATH目录下的文件,只要指定文件名就可以执行,不用指定路径(如果指定了路径,那就是execl/execv)。

execle/execve/exclpe/execvpe表示参数之后还有环境变量。

返回值:成功则执行指定进程,并覆盖原进程。失败返回-1。

参考:http://blog.chinaunix.net/uid-20583479-id-1919897.html

3)       system

属性于标准库stdlib.h。

参见system

7.6.2.3  退出进程

void exit(int status);

刷新缓冲区,返回status。

void _exit(int status);

不刷新缓冲区,直接返回status。

pid_t wait(int *status);

等待子进程退出。成功返回pid,出错返回-1。

pid_t waitpid(pid_t pid,int *status,int options);

等待指定的pid(多种选择)。成功返回pid,出错返回-1。

7.6.2.4  信号处理

int pause(void);

 

7.7 stdlib.h

int system(const char *cmd);

执行shell语句。

成功则执行指定语句,并返回子进程的返回值;失败则返回-1/127。

内部调用fork(),然后是exec()执行shell。如果exec()出错,则返回127。为了判断返回值是子进程返回的,还是错误码,需要检测errorno。

7.8 sys/resource.h

资源操作。

7.8.1进程优先级

int setpriority(int type,int id,int priority);

设置进程优先级(实际上是修正值 -20~19),su用户才能提高优先级。type:PRIO_PROCESS、PRIO_PGRP、PRIO_USER。成功返回0,失败返回-1。

int getpriority(int type,int id);

获取进程的优先级。无法判是否成功执行,需要使用errorno进行辅助。

7.9 getopt.h

参数解析。

7.9.1int getopt(int argc,char *argv[],char*opt);

判断单字符型参数。opt中的参数必须是单字符的。如:ab:c::。

如果参数后带:表示必须有一个参数值(参数与值之间可以带空格);如果参数后带::表示可以带有一个参数值,也可以不带(参数与值之间不能带空格)。

如果成功,则返回参数,参数值放入optarg中。下一个参数放入optarg。无效选项(返回?、:)放入optopt。opterr:如果设置为0,则不输出任何错误信息。

如果返回?表示参数无效;如果返回:表示需要参数值。

如果返回-1,表示参数已经解析完毕。

输入格式:

程序名 –参数字符 参数值(必选,中间可以有空格,也可以没有)

程序名 –参数字符参数值(可选,中间不能有空间)

参考:http://baike.baidu.com/view/2406693.htm?fr=wordsearch

7.9.2struct option

{

const char *name;//参数名称

int has_arg;//0:无值;1:必须带值;2:可选带值

int *flag;//返回值标志。如果为NULL(通常),则返回val;如果不为NULL,则将val的值设置为flag指向的地址,并且函数返回0。

int val;//返回值。

}

7.9.3int getopt_long(int argc,char *argv[],char*opt,struct option *opt_long,int *longindex);

getopt的字符串版。判断字符串型参数。前三个参数与getopt()一样,所以具有getopt()的所有功能。opt_long参数是一个struct option类型的结构数组,用于保存各种字符串参数。longindex是当前参数在opt_long数组中的索引值。返回值与getopt()一样。

输入格式:

程序名 --参数字符串 参数值(必选,可以使用空格或=来区分参数字符串与参数值)

程序名 --参数字符串=参数值(可选,只能用=来区分)

参考:http://www.cs.duke.edu/courses/spring04/cps108/resources/getoptman.html

7.9.4int getopt_long_only(int argc,char*argv[],char *opt,struct option *opt_long,int *longindex);

getopt_long与get_opt的综合版。可以混合字符与字符串两种格式。只有在字符串格式无法解析时,才会按照字符进行解析。

7.10 参考

http://blog.chinaunix.net/uid-26207112-id-3327014.html

 

8 文件格式

8.1 源文件

编写的原始文件。

8.2 目标文件

经过编译过后,可由CPU直接执行的二进制文件。

8.3 可执行文件

目标文件经过链接后,可以直接执行的二进制文件。

可执行文件包含三个基本section:text,data,bss。

text:文本段,存储程序。

data:数据段,存储含有数据的全局变量和静态变量。

bss:符号段,存储无数据的全局变量和静态变量符号。

8.4 可重定位文件

在链接阶段,链接器检测文件类型,并把目标文件或库文件中函数放到目标文件中,把其中的符号都放到data或BSS中。链接器不断的检测链接文件,直到BSS这空(如果BSS最后不为空,则不是可执行文件(如果要编译成可执行文件,则会报错))。

参考:

http://blog.csdn.net/czg1984/article/details/4658749

http://baike.baidu.com/view/1011029.htm?fr=wordsearch

8.5 ELF文件

ELF:executable and linking format。

包含文件头、程序头、数据头、数据区。

文件头:存储了文件类型,入口地址、程序头和区段头的指针以及文件的整体信息。

程序头:对应text段,存储程序。

数据头:对应data段,存储数据区的表单。

数据区:数据头的实际内容。

参考:

http://www.cnblogs.com/xmphoenix/archive/2011/10/23/2221879.html

8.6 core文件

程序崩溃时,系统生成的进程映像。一般用于程序调试。

使用CTRL+\退出程序时会生成core文件。

http://www.cnblogs.com/dongzhiquan/archive/2012/01/20/2328355.html

8.7 档案文件类型

Linux文件类型分为Regular File(正规文件)、目录文件(Directory)、链接(Link)、设备文件(Device)。

正规文件:一般数据文件,分为文本、二进制、数据文件,前缀为-。

目录文件:文件目录,前缀为d。

链接文件:快捷方式,前缀为l。

设备文件:特殊文件,如硬盘等存储设备(Block,前缀为b)、输入输出文件(Character,前缀为c)、管道文件(Pipe,前缀为p)。

参考:http://blog.csdn.net/tec_feng/article/details/11010467

 

9 进程

9.1 概述

进程是指运行中的程序。

进程在内存中保存各种属性数据,包括其用户、组、ID、父进程ID等。

9.2 Shell控制

cmd &:在命令后+&,可以让此进程直接进入后台运行。

jobs –l:列出所有的后台进程。

bg %n:将进程n放入后台执行。

fg %n:将进程n放入前台执行。

kill %n:关闭进程n。

ctrl + c:强制停止当前进程。

ctrl + z:将当前进程放入后台,并暂停执行。

参考:http://blog.sina.com.cn/s/blog_4fe4a26b0100dsu0.html

 

9.3 进程的内存映像

进程创建后分配4G的内存地址。在低地址装入程序的代码段(只读),数据段、BSS段,动态分配堆(heap),栈(stack,由系统管理)。

9.4 终端、会话、进程组、进程控制终端

终端:是当前系统的具体使用者。使用远程方式登陆时,称为tty。具体的文件为pst(伪终端:无实际的输入输出设备)。

会话:启动shell时,开启一个会话。退出shell时,关闭一个会话。首进程的id设置为会话id.

进程组:每个进程都唯一归属一个进程组,首个进程id就是这个进程组的组长id.

进程控制终端:进程运行时,用于与进程进行交互的进程就是控制终端。

9.5 进程的状态

RUNNING:分为两种,运行中(正在使用CPU)、就绪(正在等待CPU)。

SLEEPING:分为两种,可中断(可以被其它事件中断)、不可中断(只能等待资源)。

STOPPED:停止,多由debug引起。

ZOMBIE:已结束,正在等待系统执行wait()收尾。

9.6 进程的优先级

进程的优先级代表获得CPU的先后顺序。

范围:0~99(实时进程),100~139(非实时进程)。越小,优先级越高。

进程的优先级分为Priority和nice(-20~19)。

priority指优先级,为进程级别以上设置。nice为调整值,调整后的优先级为原来的优先级Priority+nice。只有SU可能提高优先级。

参考:

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

http://blog.csdn.net/codestinity/article/details/7496962

9.7 环境变量

9.7.1全局环境变量

/etc/profile

9.7.2用户环境变量

HOME/.bash_profile(交互式登陆方式)和HOME/.bashrc(非交互式登陆方式)

9.7.3会话级环境变量

仅用于当次会话有效。

定义:export 变量=Value

删除:unset $变量

取值:$变量

9.7.4字符串操作

查找替换字符串

echo ${目标字符串/查找的内容/替换的内容}

http://hi.baidu.com/pdaliu/item/a7bb9b35fe8543352e20c4b1

9.7.5特殊变量

$$:当前进程id。

$!:上一进程id。

$?:上一进程返回值。

$#:参数个数。

$n:第n个参数。

9.8 创建进程

子进程:fork()

新进程:exec()

外部新进程:system()

9.9 结束进程

exit():标准库函数。退出前刷新缓冲区。

_exit():系统API。退出前不刷新缓冲区。

wait():等待子进程退出。

waitpid():等待指定子进程退出。

10    信号

10.1 概述

信号,又称软中断,是进程之间传递的中断信息。

信号的处理是异步的(所谓同步,就是顺序执行,一个执行完,另一个才能执行;所谓异步就是并行执行,各自执行各自的)。

linux中有64种信号,使用kill –l可以查看所有信号。0~31是不可靠信号(有可能丢失),32~63是可靠信号(内核排队,不会丢失)。

10.2 常用信号

SIGHUP:hang up,挂断信号。在终端退出时,系统向当前终端所有进程发送。

SIGINT: interrupt,中断信号。在CTRL+C时发送。

SIGQUIT:退出信息。CTRL+\时发送。

SIGBUS:内存地址有效,但总线无法正常使用时发送的信号。

SIGSEGV:segment violation,内在地址无效时发送信号。

SIGFPE:float point error,浮点错误,如除0、数据溢出等。

SIGKILL:强制终止进程信号,立即退出,无法忽略或被用户捕获。kill -9可以发送。

SIGTERM:终止进程信号,可以被用户不活。kill可以发送。

SIGALRM:定时器信号。alarm()函数发送。

SIGCSD:子进程退出信号。如果父进程不进行忽略或处理,子进程将成为僵尸进程。

10.3 信号处理

10.3.1信号处理函数

信号处理函数应该尽量简洁,如果调用函数,则函数应该可以重入。

一般的做法是信号处理函数处理一个变量(volatile),而其它函数监控这个变量再做处理。

10.3.1.1 简单信号处理函数

格式:void fun(int SIGXX);

_sighandler_t:信号处理函数的指针。

SIG_IGN:忽略信号函数指针。

SIG_DFL:默认处理信号函数指针。

SIG_ERR:安装信号处理函数失败的指针。

10.3.1.2 详细信号处理函数

格式:void fun(int SIGXX,siginfo_t info,void*context);

siginfo_t:是一个信号的详细信息。

10.3.1.3 信号处理中的跳转

int sigsetjmp(sigjmp_buf buf,int mask);

int siglongjmp(sigjmp_buf buf,int mask);

 

 

10.3.2信号处理映射

_sighandler_t signal(intSIGXX,_sighandler_t handler);

返回原来的信息处理函数指针。

int sigaction(int SIGXX,const struct sigaction*restrict act,struct sigaction *restrict oldact);

struct sigaction

{

union

{

  void (*sighandler)(int);

  void(*sigactionHandler)(int,siginfo_t,void *);

} handler;//处理函数

  __sigset_t sigmask;//信号集

  int flags;//标志位:SIG_INTERRUPT/SIG_RESTART/SIG_SIGINFO

}

参考:http://blog.csdn.net/chenjin_zhong/article/details/6129628

http://blog.csdn.net/cccallen/article/details/5702761

10.3.3信号阻塞

信号阻塞是指通知系统暂停发送信号,将信号放入系统缓存。

每个进程有一个唯一的mask,用于设置阻塞的信号集。

10.3.3.1 信号阻塞出现的情况:

1)   信号处理函数执行过程中。

2)   sigaction中设置了mask。

3)   使用sigprocmask中设置了mask。

10.3.3.2 信号阻塞集合操作函数

int sigprocmask(inttype,const sigset_t new,sigset_t old);

设置进程的阻塞信号集。type有三类:SIG_SETMASK,SIG_BLOCK,SIG_UNBLOCK。

成功返回0,失败返回-1,以下函数返回值相同。

intsigaddset(sigset_t *set,int sig);

增加信号。

intsigdelset(sigset_t *set,int sig);

删除信号。

intsigfillset(sigset_t *set);

将全部信号写入。

intsigemptyset(sigset_t *set);

清空信号集。

intsigismember(sigset_t *set,int sig);

检查是否存在。、

intsigpending(sigset_t *set);

获取未决信号集合。

参考:

http://www.ualberta.ca/dept/chemeng/AIX-43/share/man/info/C/a_doc_lib/libs/basetrf2/sigaddset.htm

10.3.4信号等待

int pause(void);

等待阻塞信号,如果收到,则结束等待。返回值为-1,errno=EINTR。

由于pause等待的是阻塞信号,如果信号已经在阻塞mask中,则需要先取消阻塞,再进行等待。如果阻塞之后与pause()之间收到信号,则pause()就无法再处理此条信号,会导致永久等待。

int sigsuspend(sigset_t*mask);

首先设置阻塞信号集,等待阻塞信号,如果收到,处理,恢复原先的阻塞信号集,返回-1。

是Pause()的改进版本。首先取消阻塞,处理信号,恢复阻塞,返回-1。其将等待设置封闭为一个原子操作,避免了永久等待的问题。

10.3.5信号发送

1)   int kill(int pid,int sig);

向pid发送sig信号。可以发向其它进程或组。成功返回0,失败返回-1。

pid==0,当前进程组的所有进程。

pid>0,指定id的进程。

pid ==-1,发送给所有能够发送到的进程。

pid <0,发送给进程组id=abs(pid)的所有进程。

2)   int raise(int sig);

kill的本地进程版,中能向自己发送信号。

3)   int sigqueue(int pid,int sig,union sigval val);

kill的改进版,可以附加信息。成功返回0,失败返回-1。

unionsigval

    int sival_int;

    void *sival_ptr;

10.3.6定时器

unsignedint alarm(unsigned int sec);

定时器,定时发送SIGALARM信号。成功返回0或以前设置的定时器的剩余时间。

11    进程间通信 

进程间通信是指不同的进程之间交互信息。早期通过管道和信号进行通信。后来提供了共享内存、信号量、消息队列三种进程间通信(称之为IPC,Inter Process Communation)。为了解决网络进程间的通信,BSD实现了Socket技术,后来成为网络通信的标准。

管道和信号出现较早,已为各种系统实现。

IPC早期为System V,多数系统支持较好,但由于不使用命名空间,受到较多质疑,Posix IPC可移植性较好,但支持情况不一。

11.1 管道

管道本质是一种文件,由队列实现,遵循FIFO原则。在Linux下有4096Byte大小限制。

管道分为普通管道和命名管道。普通管道是一段共享内存,由亲缘关系的进程之间相互调用。命名管道则是一个具名文件,由不同的进程之间相互调用。

管道默认是半双工的,也就是说在读/写的时侯要关闭另一端。

11.1.1普通管道

11.1.1.1 创建管道

int pipe(int iStream[]);

创建普通管道。创建后将生成两个文件描述符存于iStream中。第一个是读流,第二个写流。当管道为空时,读流阻塞,等待写入;当管道写满时,写流阻塞,等待读取。

注意:fork()时会复制父进程的文件描述符。所以在子进程和父进程中都有管道文件技术符的副本,但指向的文件是同一个内存地址。

11.1.1.2 读写管道

管道在系统中被视为文件,操作也与文件操作相同。

size_t read(int iStream,char *buf,size_t count);

文件读取。参见文件读写

size_t write(int iStream,char *buf,size_t count);

文件写入。参见文件读写

11.1.1.3 关闭管道

int close(int iStream);

文件关闭。参见文件操作

关闭管道会使管道的文件描述符引用减1。但要注意,管道打开了两个文件,一个读,一个写,要分别关闭。

进程退出时,管道会自动关闭打开的文件。

11.1.1.4 快速操作管道

FILE *popen(cont char *cmd,const char *mode);

执行fork(),然后执行cmd,然后将结果输出到FILE流中。成功返回FILE,失败返回NULL。

int pclose(FILE *iStream);

关闭流。

11.1.2命名管道

普通管道是内存文件,只能在具有亲缘关系的进程间进行通信。

命名管道是一种物理文件,可以供所有的程序使用。

11.1.2.1 shell编程

命名管道作为一种文件类型,可以直接使用shell创建。

mknod name p:创建管道类型文件。

mkfifo –m 权限名称:创建fifo类型文件。

11.1.2.2 创建管道

int mkfifo(const char *path,mode_t mode);

创建命名管道文件。成功返回0,失败返回-1。

 

11.2 信号

11.3 IPC

IPC使用标识符唯一确定一个IPC对象(相当于一种指针),使用key来标识一种IPC对象(内存内容)。不能直接操作key,只能操作标识符。

11.3.1shell

ipcs –asmq

查看IPC。

ipcrm –smq/SMQ

删除IPC。

11.3.2消息队列

消息队列,在内核缓冲区中分配一块内存,用于不同的进程进行读写。读写时要进行从内核数据复制到进程数据的工作。

11.3.2.1 概述

消息

消息是指进程间传递的数据内容。消息是种结构,包含类型和数据。

队列

FIFO。读取消息时从队列头读取,写入消息时,从队列尾部写入。

11.3.2.2 队列操作

key_t ftok(const char *path,int id);

根据文件名和id生成key。成功返回key,失败返回-1。

int msgget(key_t key,int flag);

根据flag和key创建消息队列(如果存在,则返回其id),并返回标识符。成功返回标识符,失败返回-1。

注意:如果key为IPC_PRIVATE(0)时,key为0值,不能使用key获取消息队列,必须使用标识符。

注意:需要SU权限。

int msgsnd(int id,const void *pMsg,size_t size,intflag);

向指定的消息队列发送消息。成功返回0,失败返回-1。

注意:需要SU权限。

int msgrcv(int id,void *pMsg,size_t size,long intntype,int flag);

从指定的消息队列描述符(index)中读取size个字符,存入指定的消息中。成功返回读取的字符数,失败返回-1。

注意:id为标识符,不是key。

int msgctl(int id,intcmd,msgid_ds *ds);

获取指定MQ描述符的控制结构数据。成功返回0,失败返回-1。

11.3.3共享内存

共享内存的目标是将内核数据映射到进程空间。通过进程空间的指针直接操作内核数据,减少了复制过程。

11.3.3.1 操作

int shmget(key_t key,size_t size,int flag);

创建或读取已有的共享内存描述符。成功返回描述符,失败返回-1。

void *shmat(int id,const void *p,int flag);

读取描述符指定的共享内存中的内容。成功返回指针,失败返回NULL。

int shmdt(void *p);

删除共享内存。成功返回0,失败返回-1。

int shmctl(int id,int cmd,shmid_ds *ds);

获取指定SHM描述符的控制结构数据。成功返回0,失败返回-1。

11.3.4信号量

信号量是一种资源控制功能,分为P操作(占用)和V操作(释放)。

信号量用于多进程的互斥和同步。

互斥(原子操作):A进程P、操作(称为临界区)、V。

同步:A进程P,等待资源(初始设置为0,才能阻塞)-》B进程操作,V-》A进程操作。

11.3.4.1 操作

Int semget(key_t key,int n,int flag);

根据key,生成描述符。成功返回》=0的描述符,失败返回-1。

Int semctl(int id,int index,int flag,union semunbuf);

获取描述符为id的信号量的控制信息。成功返回0,失败返回-1。

Int semop(int id,struct semop *op,int n);

Struct sembuf

{

    Int index;

    Short op;

    Shortflag;

 

}

PV操作。功能返回0,失败返回-1。

12    网络

12.1 网络拓扑结构

指网络上各种设备的物理布局。

包括总线型拓扑(公共总线连接所有终端,简单、易扩展、速度受限)、星型拓扑(中央服务器服务卫星终端,简单、易实现、中央服务器压力大)、环形拓扑(通信线路闭合,简单、传输距离远、扩展性差)。

12.2       网络通信 

网络通信的建立至少需要以下几个要素:本地地址、本地端口、远端地址、远端端口、通信协议。

上述五个元素称为五元组,可以唯一的确定网络通信的两端,也称为全相关。

由地址、端口和通信协议称为三元组,可以唯一标识网络通信的一端,也称为半相关。

通信协议指网络中数据交互所遵守的规则的集合,只有使用相同的协议才能通信。

网络地址用于区分网络中不同的终端。

端口号用于区分终端中不同的网络服务。

12.3 网络分层

根据不同的功能,将网络交互过程分为不同的层次。每一层完成相应的功能。下层只能上层负责,提供其以下所有的功能。上层只针对下层的数据操作。在网络的两端,

12.3.1OSI参考模型

OSI(Open System Interconnection):由ISO(international Standardard Organization)和CCITT(Consultation Committee onInternational Telephone and Telegraph)共同制定的标准网络体系结构。

OSI分为七层结构:

应用层:各种应用协议。

表示层:主要是对数据进行格式化。

会话层:主要维持连接的有效性。

传输层:数据包传输,主要是数据传输控制,将数据进行包处理。如TCP协议。

网络层:主要是网络地址操作,解析为相应的物理地址。如路由器、IP协议。

数据链路层:帧传输,主要是bit流的帧操作,物理寻址等。如交换机。

物理层:bit流传输,主要是bit流的设备。

参考:http://baike.baidu.com/view/547338.htm?fr=wordsearch

12.3.2TCP/IP协议

由美国国防部(DOD,the UnitedStates Department of Defence)的高级研究项目管理局(APRA,Advanced Project Research Agency)研发,最初用于构建APRA网,后成为Internet。

12.3.2.1 TCP/IP分层模型

应用层:对应OSI的会话层、表示层、应用层。用于应用协议的传输。由TCP协议子类:HTTP、FTP、TELNET和UDP协议子类SNMP、TFTP、NTP等组成。

传输层:对应OSI的传输层。用于数据包的传输。由TCP(Transformation Control Protocol)和UDP(User Datagram Protocal)组成。

网络层:对应OSI的网络层,用于路由。由IP、ICMP、IGMP、ARP、RARP组成。

网络接口层:对应OSI的物理层和数据链路层,用于数据的物理传输。

参考:

http://wenku.baidu.com/link?url=7d15eznT-FriYs2xUBsb3u3HtraMVr8pl0ld9VCmlnkB8NAK_y9-1ItwDK9kvw2nv36rtyIFFInPy6E0vwg4KHF1wVvbQ6Kuv-wFUs5LR4W

12.3.2.2 TCP/IP协议簇

TCP:面向连接的可靠的全双工的传输协议。

UDP:无连接的快速传输协议。

IP:Internet Protocol。解决网络地址的问题。

ICMP:internet controlmanagement protocol,用于路由的控制协议。

ARP:Address ResolutionProtocol,地址解析协议,用于将IP地址转换为物理地址。

RARP:Reverse AddressResolution Protocol,反地址解析协议,用于将物理地址解析为IP地址。

1)   IP地址

用于区分网络上不同的主机(由IP映射到MAC(MediaAccess Control)地址(16进制,6字节))。

IPV4将地址分为32位(4个字节),5个种类。

A类:0开头,第一个字节是网络地址,3个字节是主机地址。

B类:10开头,前两个字节是网络地址,后两个字节是主机地址。

C类:110开头,前三个字节是网络地址,后一个字节是主机地址。

D类:1110开头,到1111(不包含),保留地址,用于广播。

E类:以111110开头,保留为将来使用。

特殊:全0为当前主机,全1为子网广播地址。127.0.0.1表示loopback interface(环回接口,用于本机与本机进行TCP/IP通信),并命名为localhost。

2)   端口

同一个IP地址上不同的服务之间使用端口号加以区分。端口使用四个字节。0~1023个字节保留为知名端口。TCP和UDP端口相互独立。

3)   TCP协议

面向连接的全双工、点对点、可靠的传输协议。

连接时:三次握手(1、请求连接;2、批准并请求同步;3、发送同步数据。);

断开时:四次握手。

a)   A端请求断开(A端关闭发送端,只能接收);

b)   B端允许断开(A端关闭接收端);

c)   B端请求断开(B端关闭发送端,只能接收);

d)   A端允许(B端关闭接收端);

4)   UDP协议

无连的、半双工、快速、不可靠的传输协议。

12.4 C/S模型

客户端/服务器模型:主要用于多个客户端使用大型服务器资源。主要有重复服务器(单服务重复执行)和并发服务器两种类型(多服务并发执行)。

重复服务器

等待请求-》处理请求-》回执-》重复。

单处理、资源消耗低。

并发服务器

主服务器等待请求-》接收请求-》(创建从服务器-》处理请求-》回执)并发处理-》重复。

并发处理实时性强、资源消耗高。

12.5 Socket

Socket本质上是一个内存缓冲区,在其设置了网络地址后,就可以在指定的协议族中成为网络中可用的一段内存。此后,只要有两个确定的socket(具有缓冲区的网络实体,socket只向本地缓冲区中读写数据,具体的收发工作由TCP协议实体完成),就可以进行连接,然后进行通信。

Socket每次使用一个端口,在关闭后会保持一段时间不能使用。如果一个端口被占用,则会自动分配一个闲置的端口。

12.5.1概述

12.5.1.1 地址族与协议族

定义了通信的环境。

协议族用于设置协议族,可以设置多个地址族,当前的实现方式是每个协议族对应一个地址族,所以在使用协议相关的配置时应用PF_INET,使用与地址相关的配置时,使用AF_INET。

AF_INET:Address Family Internet。地址族。BSD中使用。

PF_INET:Protocol Family Internet。协议族。POSIX中使用。

AF_INET与PF_INET是一样的,表示的概念略有不同。

PF_UNIX/PF_LOCAL/PF_FILE:本地进程间通信。

PF_INET:IPV4网络通信。

PF_INET6:IPV6网络通信。

PF_IPX:Novell IPX通信。

PF_X25:ITU-T(InternationalTelecommunication Union国际电信联盟(CCITT改名) for Tececommunication) X2.5/ISO-8208 网络通信。

参考:http://blog.csdn.net/xiongmaojiayou/article/details/7584211

12.5.1.2 Socket类型

Socket本质是一种文件类型,通过协议进行网络通信,以Socket的结构进行组织和管理。

Socket的类型:SOCK_STREAM(流式存储,面向连接有序字节流,通过TCP实现)、SOCK_DGRAM(数据报存储,无连接无序字节流,通过UDP实现)、SOCK_RAW(原始bit流,基于IP实现)、SOCK_SEQPACKET(数据包流,通过TCP实现)。

12.5.1.3 连接方式

面向连接的通信有两种,长连接和短连接。

长连接是指建立连接后,连续多次传输数据,最后断开连接。复杂(需要考虑网络异常),高效。

短连接是指建立连接后,传输一次数据,然后断开连接。简单,效率低。

12.5.1.4 数据传输方式

数据传输方式主要有两种,同步传输与异步传输。同步和异步主要是相对程序的控制流程来说的。

同步传输:数据发送后,程序等待数据返回(需要处理超时的问题),数据返回程序继续。

异步传输:数据发送后,程序立即继续执行,一般会有并行的进程处理数据返回。

12.5.2数据结构

12.5.2.1 地址结构

用于表示网络连接的地址。

1)   通用地址结构

所有地址结构的通用模板。

Struct sockadd

{

    __SOCKADDR_COMMON(sin_family);//表示地址族和长度

Char sa_data[14];//地址数据

}

2)   INET地址结构

通用地址结构的IP实现。是Internet地址的具体定义。

Struct sockadd_in

{

__SOCKADDR_COMMON(sin_family);

struct in_addr sin_addr;//IP地址

in_port sin_port;//接口

unsigned char sin_zero[];//填充数据

}

12.5.2.2 主机实体结构

在网络通信中,主机包含IP、名称等信息。

struct hostent

char *h_name;//主机名称

char **h_aliases;//主机别名数组

int h_addrtype;//地址族类型

int h_length;//地址长度

char **h_addr_list;//所有地址列表

#define h_addr h_addr_list[0]//第一个地址

};

12.5.2.3 服务实体结构

在每个主机中,不同的服务之间使用端口号区分,包含端口号,协议类型,名称,别名信息。

struct servent

{

char *s_name;

char **s_aliases;

int s_port;

char *s_proto;

}

12.5.2.4 通用收发数据结构

struct msghdr

{

    void*msg_name;

    size_tmsg_namelen;

    structiovec *msg_iov;

    void*msg_control;

    size_tmsg_controllen;

    intmsg_flags;

}

strucct iovec

{

    void*iov_base;

    size_tiov_len;

}

12.5.3辅助函数

12.5.3.1 字节序操作函数

TCP/IP协议中统一采用大端字节序。

short htons(short);

long htonl(long);

short ntohs(short);

long nttohl(long);

short:用于端口转换。long用于IP转换。

向socket发送数据时,使用hton;

从socket取数据时,使用ntoh。

12.5.3.2 地址转换函数

由于IP地址在内部交互时,一般使用32位的整型,而与用户交互时,一般使用四组十进制数据,所以需要一种两种映射的转换函数。

int inet_aton(const char *cp,struct in_addr *inp);

将字符型IP转换为32位IP。成功返回1,失败返回0。

struct in_addr

{

unsigned long int s_addr;

}

int inet_pton(int af,const char *p,void *dst)

in_addr_t inet_addr(cosnt char* cp);

char *inet_ntoa(in_addr_t);

const char *inet_pton(int af,void *src,char*p,size_t size);

12.5.4Socket函数

12.5.4.1 socket

int socket(int PF_INET,int type,intprotocol);

建立socket,主要是建立一个本地缓冲区,用于网络通信(设定缓冲区的类型,通过协议设定)。此时并不具备地址等信息。

type:SOCK_STREAM,SOCK_DGRAM,SOCK_RAW。

protocol:使用0,则根据PF和Type自动设置。可以设置为TCP,UDP,IPv6。

成功返回描述符,失败返回-1。

12.5.4.2 bind

int bind(int iSocket,struct sockadd*addr,size_t addr_len);

将socket缓冲区与ip绑定,使用socket具有网络地址。绑定后的socket可以在网络上被识别。

成功返回为0,失败返回-1。

12.5.4.3 listen

int listen(int iSocket,size_t maxcount);

指定socket为被动监听接口。

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

12.5.4.4 accept

int accept(struct sockadd *addr,size_taddr_len);

接受连接请求,并输出请求socket的信息addr和len。

成功返回可以发送数据的socket描述符(要使用这个socket进行数据传输,原来的socket还要监听),失败返回-1。

调用后accept后,如果没有连接请求,则阻塞。

12.5.4.5 connect

int connect(int iSocket,struct sockaddr *addr,size_t len);

本地socket与目标socket连接。成功返回0,失败返回-1。

要注意,在设置socket时的字节序列问题。

12.5.4.6 send/recv

size_t send(int iSocket,void *buf,size_tlen,int flag);

从连接的socket中发送、读取数据。与文件操作相同。

sendto/recvfrom:UDP数据收发。

sendmsg/recvmsg:TCP/UDP通用的数据收发功能。

12.5.4.7 close/shutdown

int close(int iSock);

关闭连接。成功返回0,失败返回-1。

12.5.4.8 getsockname/getpeername

int getsockname(int iSocket,struct sockaddr* addr,size_t &len);

int getpeername(int iSocket,struct sockaddr* addr,size_t &len);

读取本地实际分配的描述符的详细信息。peer为连接才能获取。

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

 

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/sf2gis2/article/details/50516985

智能推荐

普元DevOps平台的安全可靠设计_EAWorld的博客-程序员宝宝

转载本文需注明出处:微信公众号EAWorld,违者必究。引言:普元DevOps平台覆盖从需求到运维,力求帮助团队提升工作效率、保障系统质量。在安全可靠层面,平台需要考虑自...

C/C++头文件一览[转]_hu17889的博客-程序员宝宝

<br />C/C++头文件一览 <br />C、传统 C++<br /><br />#include <assert.h>//设定插入点<br />#include <ctype.h> //字符处理<br />#include <errno.h> //定义错误码<br />#include <float.h> //浮点数处理<br />#include <fstream.h> //文件输入/输出<br />#include <iomanip.h> //参数化输入/输出<br />#include <ios

# Alpha冲刺2_didou8933的博客-程序员宝宝

团队信息队名:爸爸饿了组长博客:here作业博客:here组员情况组员1(组长):王彬过去两天完成了哪些任务与前后端敲定接口设计的细节重新理清业务逻辑,对项目最初的设想进行一定修正跟踪各端的进展情况成功完成安卓前端与服务器的交互测试复习廖雪峰的git教程接下来的计划 &amp; 还剩下哪些任务完成接口文档编写继续跟进团队的项目进度,预计会组织一次全队...

论文阅读笔记_Deep Learning for Precipitation Nowcasting: A Benchmark and A New Model (TrajGRU)_gXh_007的博客-程序员宝宝

ConLSTM:卷积递归结构是位置不变的的,但自然运动通常位置可变。TrajGRU:修改递归结构本身,修改旋转和缩放等运动模式。论文提出一个基准:1.算法离线设置只能使用一个固定的窗口前的雷达回波地图。2.在线设置是使用所有历史数据和在线学习算法。TrajGRU使用子网,在状态转换前输出状态的连接结构。降水预报问题:首先将雷达回波图中的反射率因子转化为灰度图像,然后将其输入到预报算法中。因此,降水临近预报可以看作是一种带有固定“摄像机”的视频预报问题,“摄像机”就是天气雷达。TrajGRU的目

DPDK-实战之ipsec-secgw(安全网关)_庞叶蒙的博客-程序员宝宝

0x01 缘由    看到了比较陌生的名词觉得比较高大上,于是想探究下。0x02 介绍    IPsec 安全网关应用是用DPDK cryptodev框架的一个实际应用例子。    这个应用说明用DPDK实现的一个安全网关,基于RFC4301, RFC4303, RFC3602、RFC2404标准。IKE不实现,因此仅仅手动设置安全策略。    安全策略(SP)用ACL规则实现

超硬核Java工程师秋招回忆录+面经汇总,为了拿BAT的研发offer我都做了那些准备?_黄小斜的博客-程序员宝宝

秋招总结写在最前我写过很多篇秋招总结,这篇文章应该是最后一篇总结,当然也是最完整,最详细的一篇总结。秋招是我人生中一段宝贵的经历,不仅是我研究生生涯交出的一份答卷,也是未来职业生涯的开端。仅以此文,献给自己,以及各位在求职路上的,或者是已经经历过校招的朋友们。不忘初心,方得始终。前言在下本是跨专业渣考研的985渣硕一枚,经历研究生两年的学习积累,有幸于2019秋季招聘中拿到几个公司的研发岗offer,包括百度,阿里,腾讯,今日头条,网易,华为等。(在秋招末期,有幸又拿到了滴滴和亚马逊的offer,

随便推点

Retry优雅的失败重试策略_suhuaiqiang_janlay的博客-程序员宝宝

从零开始nodejs系列文章,将介绍如何利Javascript做为服务端脚本,通过Nodejs框架web开发。Nodejs框架是基于V8的引擎,是目前速度最快的Javascript引擎。chrome浏览器就基于V8,同时打开20-30个网页都很流畅。Nodejs标准的web开发框架Express,可以帮助我们迅速建立web站点,比起PHP的开发效率更高,而且学习曲线更低。非常适合小型网站,个性化网...

Data truncated for column ‘xxxxx‘ at row 1错误_小白鼠666的博客-程序员宝宝

当出现Data truncated for column ‘xxxxx’ at row 1这个错误时还有一种可能就是你的sql语句写错了。

EOS区块链技术开发(〇)起源_币乎是用eos来开发的吗_treaser的博客-程序员宝宝

EOS区块链技术开发(〇)起源1 Why1.1 EOS区块链1.2 CSDN2 How3 What参考资料2018年10月份开始,我加入了学校的区块链协会。这不仅是因为我觉得区块链是我研究生会从事的事业,更重要的是,我把区块链当做我人生第一桶金会诞生的地方。我本科并不是CS或者SE的,但是通过本科这三年对计算机知识的兴趣与学习、本科自己专业的绩点、暑假对于408科目的复习,最终我拿到了自己学院的...

BAT基础知识_码码人生的博客-程序员宝宝

第一章 批处理基础第一节 常用批处理内部命令简介批处理定义:顾名思义,批处理文件是将一系列命令按一定的顺序集合为一个可执行的文本文件,其扩展名为BAT或者CMD。这些命令统称批处理命令。小知识:可以在键盘上按下Ctrl+C组合键来强行终止一个批处理的执行过程。了解了大概意思后,我们正式开始学习.先看一个简单的例子[email protected] offecho &quot;欢迎来到非常BAT!&quot;pause把上面...

【Iphone 游戏开发之二】Cocos2D 游戏开发资源贴 _lishuai05251986的博客-程序员宝宝

 这两天抽出一些时间学习cocos2d,发现资料N多,而且讲解的相当的全面;那么这段时间我也处于不断的学习中,当然好东西不私藏,这里我把比较经典的一个iOS游戏开发书籍给出,当然很多童鞋,我想都有了,那么就当是照顾没有的童鞋啦,下次发帖的时候,就应该是自己抽时间做个游戏出来后的时候,那么届时我会放出游戏源码给大家作为参考和学习;后期再写会写一些至少别人没有写过的,不然没什么太大的意义; ...

推荐文章

热门文章

相关标签