DREAM OF TECHNICAL ACHIEVEMENT

0%

Socket编程

套接字概念

Socket本身有“插座”的意思,在Linux环境下,用于表示进程间网络通信的特殊文件类型。本质为内核借助缓冲区形成的伪文件。

既然是文件,那么理所当然的,我们可以使用文件描述符引用套接字。与管道类似的,Linux系统将其封装成文件的目的是为了统一接口,使得读写套接字和读写文件的操作一致。区别是管道主要应用于本地进程间通信,而套接字多应用于网络进程间数据的传递。

套接字的内核实现较为复杂,不宜在学习初期深入学习。

在TCP/IP协议中,“IP地址+TCP或UDP端口号”唯一标识网络通讯中的一个进程。“IP地址+端口号”就对应一个socket。欲建立连接的两个进程各自有一个socket来标识,那么这两个socket组成的socket pair就唯一标识一个连接。因此可以用Socket来描述网络连接的一对一关系。

阅读全文 »

同步概念

所谓同步,即同时起步,协调一致。不同的对象,对“同步”的理解方式略有不同。如,设备同步,是指在两个设备之间规定一个共同的时间参考;数据库同步,是指让两个或多个数据库内容保持一致,或者按需要部分保持一致;文件同步,是指让两个或多个文件夹里的文件保持一致。等等…

而,编程中、通信中所说的同步与生活中大家印象中的同步概念略有差异。“同”字应是指协同、协助、互相配合。主旨在协同步调,按预定的先后次序运行。

线程同步

同步即协同步调,按预定的先后次序运行。

线程同步,指一个线程发出某一功能调用时,在没有得到结果之前,该调用不返回。同时其它线程为保证数据一致性,不能调用该功能。

举例1: 银行存款 5000。柜台,折:取3000;提款机,卡:取 3000。剩余:2000

举例2: 内存中100字节,线程T1欲填入全1, 线程T2欲填入全0。但如果T1执行了50个字节失去cpu,T2执行,会将T1写过的内容覆盖。当T1再次获得cpu继续 从失去cpu的位置向后写入1,当执行结束,内存中的100字节,既不是全1,也不是全0。

阅读全文 »

信号概念

信号其实我们也见过,当我们在shell上写出一个死循环退不出来的时候,只需要一个组合键,ctrl+c,就可以解决了,这就是一个信号,但是真正的过程并不是那么简单的。

  1. 当用户按下这一对组合键时,这个键盘输入会产生一个硬件中断,如果CPU正在执行这个进程的代码时,则该进程的用户代码先暂停执行,用户从用户态切换到内核态处理硬件中断

  2. 终端驱动程序将这一对组合键翻译成一个SIGINT(ctrl+c)信号记在该进程的PCB中(也就是发送了一个SIGINT信号给该进程)

  3. 当某个时刻要从内核态回到该进程的用户·空间代码继续执行之前,首先处理PCB中的信号,发现有一个SIGINT信号需要处理,而这个信号的默认处理方式是终止进程,所以直接终止进程,不再返回用户空间执行代码。

  4. shell可以同时运行一个前台进程和多个后台进程,只有前台进程才能收到ctrl+c这种组合键产生的信号

  5. 前台进程在 运行过程中用户可以随时按下ctrl+c产生一个信号也就是说前台进程的用户空间代码执行到任意一个时刻都可能接收到SIGINT信号而终止,所以信号对于进程的控制流来说是异步的。

阅读全文 »

孤儿进程

父进程先于子进程结束,则子进程称为孤儿进程,子进程的父进程成为 init 进程,称 init 进程领养进程孤儿进程,init 进程称为孤儿院。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>

int main(void)
{
pid_t pid;

pid = fork();

// 创建失败
if( pid == -1 )
{
perror("fork");
exit(1);
}
// 父进程
else if( pid > 0)
{
printf("This is the parent process. My PID is %d.\n",getpid());

sleep(4);

printf("--------------parent going to die------------------\n");
}
// 子进程
else if(pid == 0)
{
while(1)
{
printf("This is the child process. My PID is: %d. My PPID is: %d.\n",getpid(),getppid());

sleep(1);
}
}

return 0;
}
阅读全文 »

所谓的库就是一种可执行代码的二进制形式,可以被操作系统载入内存执行。

静态库和动态库

静态库 .a

文件的命名方式:“libxxx.a”,库名前加“lib”,后缀是“.a”,库名是“xxx”

链接时间:静态库的代码是在编译过程中被载入到程序中的

链接方式:静态库的链接是将整个函数库的所有数据都合成进了目标代码,优点是编译后的执行程序不需要外部的函数库支持,因为所使用的函数已经被编进去了;缺点是如果所使用的静态库发生更新改变,则需要重新编译生成静态库。

动态库 .so

文件命名方式:“libxxx.so”,库名前加“lib”,后缀是“.so”,库名是“xxx”

链接时间:动态库在编译时并没有被编译进目标代码,而是当你的程序执行到相关函数的时候才调用该函数库里的相应函数。缺点是函数库并没有整合进程序,所以程序的运行环境必须提供相应的库;优点是动态库的改变不影响程序。

阅读全文 »

什么是线程

线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。在Unix System V及SunOS中也被称为轻量进程(lightweight processes),但轻量进程更多指内核线程(kernel thread),而把用户线程(user thread)称为线程。

线程是独立调度和分派的基本单位。线程可以为操作系统内核调度的内核线程,如Win32线程;由用户进程自行调度的用户线程,如Linux平台的POSIX Thread;或者由内核与用户进程,如Windows 7的线程,进行混合调度。

同一进程中的多条线程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符和信号处理等等。但同一进程中的多个线程有各自的调用栈(call stack),自己的寄存器环境(register context),自己的线程本地存储(thread-local storage)。
一个进程可以有很多线程,每条线程并行执行不同的任务。

阅读全文 »

程序和进程

  • 程序,是指编译好的二进制文件,在磁盘上,不占用系统资源(cpu、内存、打开的文件、设备、锁….)

  • 进程,是一个抽象的概念,与操作系统原理联系紧密。进程是活跃的程序,占用系统资源。在内存中执行。(程序运行起来,产生一个进程)

程序 → 剧本(纸)

进程 → 戏(舞台、演员、灯光、道具…)

同一个剧本可以在多个舞台同时上演。同样,同一个程序也可以加载为不同的进程(彼此之间互不影响)

如:同时开两个终端。各自都有一个bash但彼此ID不同。

并发

并发,在操作系统中,一个时间段中有多个进程都处于已启动运行到运行完毕之间的状态。但,任一个时刻点上仍只有一个进程在运行。

例如,当下,我们使用计算机时可以边听音乐边聊天边上网。 若笼统的将他们均看做一个进程的话,为什么可以同时运行呢,因为并发。

分时复用cpu

单道程序设计

阅读全文 »

map/multimap的简介

  • map是标准的关联式容器,一个map是一个键值对序列,即(key,value)对。它提供基于key的快速检索能力。
  • map中key值是唯一的。集合中的元素按一定的顺序排列。元素插入过程是按排序规则插入,所以不能指定插入位置。
  • map的具体实现采用红黑树变体的平衡二叉树的数据结构。在插入操作和删除操作上比vector快。
  • map可以直接存取key所对应的value,支持[]操作符,如map[key]=value。
  • multimap与map的区别:map支持唯一键值,每个键只能出现一次;而multimap中相同键可以出现多次。multimap不支持[]操作符。

头文件 #include <map>

map and multimaps

map/multimap采用模板类实现,对象的默认构造形式:

阅读全文 »

set/multiset的简介

  • set是一个集合容器,其中所包含的元素是唯一的,集合中的元素按一定的顺序排列。元素插入过程是按排序规则插入,所以不能指定插入位置。
    set采用红黑树变体的数据结构实现,红黑树属于平衡二叉树。在插入操作和删除操作上比vector快。
  • set不可以直接存取元素。(不可以使用at.(pos)与[]操作符)。
  • multiset与set的区别:set支持唯一键值,每个元素值只能出现一次;而multiset中同一值可以出现多次。
  • 不可以直接修改set或multiset容器中的元素值,因为该类容器是自动排序的。如果希望修改一个元素值,必须先删除原有的元素,再插入新的元素。

头文件 #include <set>

图解

set/multiset对象的默认构造

  • set<int> setInt; //一个存放int的set容器。
  • set<float> setFloat; //一个存放float的set容器。
  • set<string> setString; //一个存放string的set容器。
  • multiset<int> mulsetInt; //一个存放int的multi set容器。
  • multi set<float> multisetFloat; //一个存放float的multi set容器。
  • multi set<string> multisetString; //一个存放string的multi set容器。
阅读全文 »

List简介

  • list是一个双向链表容器,可高效地进行插入删除元素。
  • list不可以随机存取元素,所以不支持at.(pos)函数与[]操作符。It++(ok) it+5(err)

头文件 #include <list>

list对象的默认构造

list采用采用模板类实现,对象的默认构造形式:list<T> lstT;
如:

  • list<int> lstInt; //定义一个存放int的list容器。
  • list<float> lstFloat; //定义一个存放float的list容器。
  • list<string> lstString; //定义一个存放string的list容器。
  • list<xxxx> lstXxxx; //定义一个存放xxxx的list容器。
阅读全文 »