4·Linux应用编程和网络编程---Linux进程全解 笔记(进程与程序的区别)


1. 程序的开始与结束

1·1 main函数由谁调用

说main函数由系统调用是不准确的。操作系统下的应用程序在main执前需要执行一段引导代码(裸机中的汇编代码)才能去执行main,所以我们在写应用程序时不用考虑引导代码的问题(做裸机开发和驱动需要)。编译链接时由链接器中事先准备好的引导代码和我们的应用程序一起构成最终的可执行程序。

可执行程序运行时需要加载器。加载器是操作系统中的程序,当我们去执行一个程序时(比如./a.out,比如代码中用exec族函数来运行)加载器负责将这个程序加载到内存中去执行这个程序

程序在编译过程中用到链接器,运行时用加载器,这两个东西对程序运行非常重要。

argc 与 argc[ ] 传参的实现原理:先传给引导代码,引导代码再传给main函数。

1·2 程序如何结束

(1)正常终止:return , exit ,_exit

(2)非正常终止:自己或他人发 信号 终止进程

1·3 atexit注册进程终止处理函数

atexit函数是在进程被正常终止时,去调用atexit注册的函数。

// atexit注册一个进程终止处理函数
#include<stdio.h>
#include <stdlib.h>

void test_func1(void)
{
	printf("this is text function1 1\n");
}
int main(void)
{
	printf("aaahhbfivn\n");

// 当进程被正常终止时,系统会自动调用这里注册的test_func1函数执行
	atexit(test_func1);


	printf("after then\n");
	return 0;
}


结果:
aaahhbfivn
after then
this is text function1 1
注意代码的打印信息的对比


所以,atexit函数就是在这个进程终止前才去调用注册的函数。

 // atexit 注册多个进程处理函数
#include<stdio.h>
#include <stdlib.h>

void test_func1(void)
{
	printf("this is text function1\n");
}
void test_func2(void)
{
	printf("this is text function2\n");
}
void test_func3(void)
{
	printf("this is text function3\n");
}

int main(void)
{

	printf("aaahhbfivn\n");

// 当进程被正常终止时,系统会自动调用这里注册的test_func1函数执行
	atexit(test_func1);
	atexit(test_func2);
	atexit(test_func3);
// 结论:先注册的后执行,后注册的先执行


	printf("after then\n");

	return 0;
}

结果:
aaahhbfivn
after then
this is text function3
this is text function2
this is text function1

所以:先注册的后执行,后注册的先执行 ,类似于 压栈与 出栈


1·4 return , exit ,_exit 的区别

return 和 exit效果一样,都是会执行进程终止处理函数,但是用 _exit 终止进程时并不执行atexit注册的进程终止处理函数

2· 进程环境

2·1 环境变量

(1)export命令查看环境变量
(2)进程环境表介绍
进程环境表:每一个进程中都有一份所有环境变量构成的表。也就是说当前进程中可以直接使用这些环境变量(进程环境表其实是一个字符串数组,用environ来指向它)。

程序中通过 environ全局变量 (系统的) 使用环境变量。

// environ 全局变量的用法
#include<stdio.h>

int main (void)
{
	extern  char **environ;//environ 是全局变量,声明就能用
	// 注意加extern关键字

	int i = 0;
	while(NULL != environ[i])
	{

		printf("%s\n",environ[i]);
		i++;
	}
	return 0;
}
结果就是打印出全部环境变量


我们写的程序中可以无条件直接使用系统中的环境变量,所以一旦程序中用到了环境变量,那么这个程序就和操作系统有关联了,因为不同的操作系统的环境变量可能不同,所以移植后就会有问题。

2·2 getenv函数获取环境变量

获取当前进程用到的环境变量,putenv,setenv是设置进程环境变量,当这个进程完成后被销毁,那么所设置的环境变量就会复原。

2·3 进程运行的虚拟地址空间

(1)操作系统中每个进程在 --独立地址空间–中运行

(2)每个进程的逻辑地址空间均为4GB(32位系统)

(3)0—1G为OS,1–4G为应用

(4)虚拟地址到物理地址的映射

(5)意义:进程隔离,为了安全性,提供多进程运行环境。

小结:每个进程都认为自己是在4G大的内存空间运行,其实它们认为的4G内存空间只是一个虚拟地址空间,这个虚拟地址空间映射到 物理地址空间也就才几兆十几兆而已。虚拟内存空间是虚幻的,物理内存空间是真真实实的。

3· 进程

3·1 什么是进程?

(1)进程是一个过程,是动态过程而不是静态实物

(2)进程就是程序的一次运行过程,一个静态的可执行程序 a . out 的一次运行过程就是一个进程。

(3)进程控制块PCB,内核中专门用来管理一个进程的数据结构

3·2 进程ID

指令:ps 或者 ps - a 或者 ps - aux 查看当前终端的进程信息。

(1)
getpid(获取当前进程pid) ,
getppid(获得当前进程的父进程pid) ,

getuid(获取当前进程的 用户ID ) ,
geteuid(获取当前进程有效用户ID) ,
getgid (获取当前进程的组ID),
getegid(获取当前进程有效组ID)


pid_t getpid(void);

pid_t getppid(void);

getpid() returns the process ID (PID) of the calling process. (This is often used by rou‐
tines that generate unique temporary filenames.)

getppid() returns the process ID of the parent of the calling process. This will be either
the ID of the process that created this process using fork(), or, if that process has already
terminated, the ID of the process to which this process has been reparented (either init(1)
or a “subreaper” process defined via the prctl(2) PR_SET_CHILD_SUBREAPER operation).

(2)实际用户ID 和 有效用户ID区别(百度)

3·3 多进程 {调度} 问题

(1)操作系统同时运行多个进程

(2)(单核CPU)宏观上的并行 和 微观上的串行

(3)实际上现代出栈系统最小的调度单元是线程而不是进程

4· fork创建子进程

4·1 为什么要创建子进程

(1)每一次程序的运行都需要一个进程,所以需要创建进程来使程序运行。

(2)多进程实现宏观上的并行
在这里插入图片描述

4·2 fork的内部原理

(1)如果操作系统需要一个新进程,那么操作系统就会用一个现有进程来复制一个生成一个新进程。

进程1 被fork后 产生 进程2,其实就是fork把进程1 ”复制“(或者说:分裂生长模式)一份,产生了进程2。所以,进程1 就是 进程2 的父进程,进程2 就是 进程1 的子进程。

(2)fork函数
fork函数调用一次会返回2次,返回值等于0的就是子进程,返回值大于0的就是父进程。

由于ork就是将旧进程(父进程)复制一份形成新进程(子进程),所以父进程 与 子进程的PCB极为相像,并且fork之后的代码段在父子进程中都有一份,并且一模一样。所以fork之后的程序在父子进程中都会执行,因为父子进程中都有这段代码。

在这里插入图片描述

#include<stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main (void)
{
	int val = -1;
	val = fork();

	if(val == 0)
	{
	// 这里是子进程
		printf("this is childP:%d\n",val);
	}
    if(val > 0)
	{
	// 这里是父进程
		printf("this is fatherP:%d\n",val);
	}
	if(val < 0)
	{
		printf("fork error!\n");
	}

// 这是fork之后的代码段,在父子进程中都有,所以在父进程和子进程中都会执行
	printf("test test test!!pid = %d\n",getpid());

	return  0;
}


结果:
this is fatherP:5793
test test test!!pid = 5792 //这个是父进程的pid
this is childP:0
test test test!!pid = 5793

父子进程运行没有先后

发现:fork的大于0的返回值既表示父进程,也代表子进程的进程ID(pid)。
可以这样理解:
父进在fork之前的进程ID(也就是pid)为5792,后来fork了,
fork就把父进程pid就加15793标识父进程这个进程,
并且把这个5793当作子进程的pid,
fork另一个返回值0就标识子进程这个进程

简而言之就是:
fork的返回值在子进程中等于0,在父进程中等于本次fork创建的子进程的进程ID。

(3)父子进程的关系

(1)子进程虽然是通过父进程复制过来的,但是子进程有自己独立的PCB
(2)子进程被内核同等调度

5· 父进程对文件的操作

5·1 子进程 继承 父进程中打开的文件

父进程先open打开一个文件得到fd,然后在fork创建子进程。之后在 父子进程 中各自write 向fd中写入内容。
测试结果:接续写。实际上本质原因是父子进程之间的fd对应的文件指针是彼此关联的(有点像O_APPEND标志)
实际测试的时候有可能会现象有点像分别写,但是实际不是,原因是父子进程中write到fd后速度快的那一个进程直接close(fd);了,所以慢的那一个进程还没来得及写。所以出现分别写的现象。

5·2 父子进程各自独立打开同一文件实现共享

(1)父进程open打开1.txt然后写入,子进程打开1.txt然后写入,结果:分别写。
原因:父子进程分离后才各自打开的1.txt,这时候两个进程的PCB已经独立,文件表也独立了,所以2次读写是完全独立的。

(2)open使用O_APPEND标志看看是什么结果?
测试结果:O_APPEND标志可以把父子进程各自独立打开的fd文件的文件指针给关联起来,实现接续写

5·3 总结

(1)父子进程之间还是会有一定的联系

(2)父进程在 [没有fork之前] 做的事对子进程有很大影响,但是父进程fork之后在自己的if里面做的事情就不会对子进程有影响,那是没有关系。本质原因:fork会父进程的PCB生成一个新的子进程,并且fork返回时子进程已经完全和父进程脱离并且独立被OS调度执行。

(3)子进程的最终目的是要独立去运行另外的程序。

6· 进程的诞生与消亡

6·1 进程的诞生

(1)进程0 与 进程1
进程0 :操作内核启动时手工构建出来的
进程1 :由进程0 fork 出来的。【内核态】

从进程2开始,就进入到【用户态】底下。

(2)fork

(3)vfork
vfork与fork的区别:
这是一位博主写的二者的区别,比喻很形象!

6·2 进程的消亡

(1)正常终止 和 异常终止

程序 与 进程:
程序就是一个静态的东西,安静的躺在硬盘里面。

进程就程序的执行的过程内存里面执行),是动态的,是一个过程,不是一个事物。

进程在运行时需要消耗系统资源(内存,IO),进程终止时应该要释放锁占用的资源,如果进程消亡后没有释放相应的资源则这些资源就丢失了。

(2)Linux操作系统设计时规定:每一个进程终止时,操作系统会自动回收这个进程涉及到的所有资源

比如malloc申请的内容没有free,在当前进程结束时这个内存会被释放;比如open打开的文件没有close,在进程的结束时也会被关闭。

但是操作系统只是回收这个进程执行时所消耗的内存与IO,并没有回收这个进程本身占用的内存(比如是 8kb,主要是task_struck 和 栈内存)。所以每一个进程都需要一个它的父进程来给它收尸

6·3 僵尸进程

(1)子进程比父进程先结束。子进程结束后父进程此时不一定立即就能帮子进程收尸,在这一段(子进程已经结束并且父进程尚未帮其收尸)子进程就成为僵尸进程。子进程除了task_struct和栈 外其他的内存已经被释放。

(2)父进程帮子进程收尸的方法:用wait或者waitpid以 显式回收 子进程的剩余待回收内存资源并且获取子进程退出状态。

父进程也可以不用调用wait或者waitpid回收子进程,此时父进程结束时一样会回收子进程的剩余待回收内存资源。(这个设计是防止父进程忘记显式调用wait或者waitpid来回收子进程从而造成内存泄漏)

6·4 孤儿进程

(1)父进程比子进程先结束。子进程变成以孤儿进程。
Linux系统规定:由于孤儿进程没有其父进程来给它收尸,所以Linux系统规定所有孤儿进程都自动成为一个特殊进程的子进程(这个特殊进程就是进程1,init进程)。

7· 父进程wait回收子进程

7·1 wait的工作原理

(1)子进程结束时,操作系统给它的父进程发送几个SIGCHILD信号。父进程调用wait函数后阻塞,直到接收到系统发送的SIGCHILD信号,然后去回收僵尸子进程

由此可以看出:父子进程之间是异步的。SIGCHILD信号机制是为了解决父子进程之间的异步通信问题,让父进程可以及时去回收僵尸子进程。

(2)如果父进程没有任何子进程则wait返回错误。

7·2 wait实战

(1)pid_t wait(int *wstatus);
wait的参数:没有const修饰 ,所以是输出型参数。wstatus 用来返回子进程结束时的状态,父进程通过wait得到wstatus后就可以知道子进程的一些结束状态信息。

(2)wait的返回值pid_t ,这个返回值就是本次wait回收的子进程的pid。当前进程可能由多个子进程,wait函数阻塞直到其中一个子进程结束wait就会返回,wait的返回值就可以用来判断到底哪一个子进程本次被回收了。
wait主要是用来回收子进程资源,回收同时还可以得知回收子进程的pid和退出状态。

(3)wait输出型参数的宏来获取回收子进程状态

WIFEXITED(wstatus)
用来判断子进程是不是正常终止(return,exit,_exit)

WIFSIGNALED(wstatus)
判断子进程是否非正常终止

WEXITSTATUS(wstatus)
得到正常终止的情况下的子进程return的值。

(4)fork后wait回收实例

#include<stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>

int main (void)
{
	pid_t val = -1;
	pid_t ret = -1;
	int status = -1;

	val = fork();

	if(val < 0)
	{
		perror("fork");
		return -1;

	}

	else if(val > 0)
	{
		printf("this is father,father pid = %d\n",getpid() );

		ret = wait(&status);
		printf("子进程已经被回收,子进程pid = %d\n",ret);

		printf("是否正常退出子进程:%d\n",  WIFEXITED(status));
		printf("是否非正常退出子进程:%d\n",  WIFSIGNALED(status));
		printf("子进程正常终止所返回的值:%d\n",  WEXITSTATUS(status));

	}

	else
	{
		printf("this is child,child pid = %d\n",getpid() );
		return 23;
	}


	return 0;
}

结果:
this is father,father pid = 21380
this is child,child pid = 21381
子进程已经被回收,子进程pid = 21381
是否正常退出子进程:1
是否非正常退出子进程:0
子进程正常终止所返回的值:23

注意:1·父子进程执行的先后顺序是不一定的。

2·子进程结束后父进程才可以从wait处阻塞结束
,去回收子进程。但是如果子进程里面有一个死循环,
那父进程就会一直阻塞,那父进程就相当于 死锁了。

3·wait函数原理:父进程调用wait函数后会阻塞在这个函数处,
直到操作系统给父进程发送一个子进程终止的信号,
父进程结束到后就跑去回收子进程占用的tast_struct 和 栈空间。

8· waitpid介绍

8·1 waitpid和wait差别

(1)基本功能一样,都是用来回收子进程
(2)waitpid可以回收指定pid的子进程
(3)waitpid可以阻塞式或者非阻塞式两种工作模式

ret = waitpid(-1, &status, 0);
-1 表示不等待某个特定pid的子进程而是回收任意一个子进程,0表示用默认的方式(阻塞式)来进行等待,返回值ret是本次回收的子进程的pid。

ret = waitpid(pid, &status, 0);

ret = waitpid(pid, &status, WNOHANG);

8·2 竟态

(1)竟态全称:竞争状态,多进程环境下,多个进程同时抢占系统资源(内存,cpu,文件IO)
(2)竞争状态对操作系统来说是危险的,此时操作系统如果没有处理好就会造成结果不确定。
(3)所以我们写程序时候要尽量消灭竞争状态,操作系统给我们提供了一系列的消灭竞态的机制,我们需要做的就是在合适的地方使用合适和方法来消灭竞态

9· exec族函数

9·1 为什么需要exec函数

父进程fork出一个子进程后,其目的就是希望父子进程同时被OS调度执行,所以子进程可以单独执行一个程序。子进程单独执行一个程序的方法有两种,第一种就是在子进程中贴上源码。这一种方法可行,但是不灵活,原因是我们必须知道源代码,而且源代码过长也不好控制。
第二种方法就是exec函数族。exec族函数可以直接把一个编译好的可执行程序直接加载运行。

9·2 exec族的6个函数介绍

(1)execl 和 execv
这两个函数是基本的exec族函数,都是用来执行一个程序,区别是传参的格式不同。exec是把参数列表(本质上是多个字符串,必须以NULL结尾,第一个参数arg[0]好像对程序没有太大的影响,第二个参数arg[1]才是对path的可执行程序传第一个参)依次排列而成,l 就是 list的缩写。execv是把参数列表事先放入一个字符串数组中,再把这个字符串数组传给execv函数。
int execl(const char *path, const char arg, … / (char *) NULL */);

int execv(const char *path, char *const argv[]);

(2)execlp 和 execvp
上面两个执行可执行程序是必须指明全路径。
这两个函数,第一个传参,可以是全路径,也可以是file,只不过会先去找file,找到则执行,如果没找到,则会去环境变量PATH所指定的目录去找,找到则执行没找到则报错。

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

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

(3)execle 和 execvpe
在这里插入图片描述

int execle(const char *path, const char arg, … /, (char *) NULL, char * const envp[] */);

int execvpe(const char *file, char *const argv[], char *const envp[]);

10· 进程状态和system函数

10·1 进程的5种状态

(1)就绪态
这个进程当前所有运行条件就绪,只要得到了cpu时间就能直接运行。

(2)运行态
就绪态得到cpu就进入运行态开始运行

(3)僵尸态
进程已经结束但是父进程还未来得及回收

(4)等待态(浅度睡眠和深度睡眠)
进程在等待某个条件,条件达到后就可以进入就绪态;等待态下就算得到cpu调度,进程也无法执行。浅度睡眠:等待时 进程可以被(信号)唤醒。深度睡眠:等待时 不能被唤醒,只有达到等待的条件才能结束睡眠状态。

(5)暂停态
暂停态不是进程的终止,只是被信号暂停了,还是可以恢复的。

10·2 进程状态之间的转换图

在这里插入图片描述

10·3 system函数

(1)system函数 就相当于 fork + exec
但是system是原子操作,而fork和exec是非原子操作。什么是原子操作?原子操作就算整个操作一旦开始就不会被打断的直到执行完。原子操作的好处就是不会被人打断,也就不会引来竞争状态;坏处就是独占cpu时间太长从而影响整体实时性。

(system 调用 ls)

11· 进程关系

(1) 无关系
(2)父子进程:父进程给子进程收尸;父子进程在fork之前的进程控制块(PCB)极为相似。

(3)进程组
若干进程构成一个进程组

(4)会话
会话就是进程组的组

12· 守护进程

12·1 进程查看命令 ps

(1)ps -ajx
显式各种有关ID号:PID PGID SID TTY等等

(2)ps -aux
显式进程各种占用资源

12·2 kill指令

(1)kill -信号编号 进程ID:向一个进程发送 信号编码 信号

(2)kill -9 xxx :结束pid为xxx的进程

12·3 什么是守护进程

(1)daemon :守护进程;后台程序.简称为d(进程名称后面带一个d的基本为守护进程,但是排除进程名称本来最后就是d字母)
(2)长期运行:一般是开机运行,关机时关闭。
(3)与控制台脱离:
普通进程都和运行该进程的控制台(终端)绑定,如果终端被强制关闭了则终端的所有进程都会关闭,背后的问题还会在于会话。

守护进程就因为与终端脱离,所以守护进程才得以 实现长期运行。

(4)服务器(server)
守护进程一般就是服务器程序。服务器程序 就是一个一直在运行的程序,可以给我们提供某种服务,档位吗需要这种服务时我们可以调用服务器程序来实现这种服务操作。

常见守护进程:
(1)syslogd :系统日志守护进程,提供syslogd功能。
(2)cron :cron进程用来实现操作系统的时间管理,Linux中实现定时执行程序的功能就要用到cron。

14· 简单守护进程的编写

(1)任何一个进程都可以将自己实现成守护进程

(2)create_daemon 函数要素
第一,fork之后,子进程运行子进程特有函数,就需要让父进程直接退出。
第二,子进程使用setsid创建新的会话期,脱离控制台
第三,调用chdir将当前工作目录设置为当前目录 /
第四,umask设置为0 用以取消任何文件权限屏蔽
第五,关闭所有文件描述符
第六,将fd为0、1、2定位到 /dev /null(这是一个字符设备文件,相当于是一个回收站)

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

#include <sys/stat.h>
#include <fcntl.h>


void creat_daemon(void);


int main (void)
{

	creat_daemon();

	while(1)
	{

		printf("hollow\n");

	}

	return 0;
}


// 函数的作用:把调用整个函数的进程变成守护进程
void creat_daemon(void)
{
	pid_t val = -1;
	pid_t pid = -1;

	val = fork();

	if(val < 0)
	{
		perror("fork");
		exit(-1);
	}

	if(val == 0)
	{
		exit(0);
	}


// 执行到这里就一定是子进程
	pid = setsid();
	// setsid就是将当前进程设置为一个新的会话期session
	// 目的就是让当前进程脱离控制台
	if(pid < 0)
	{
		perror("setsid");
		exit(-1);
	}

	chdir("/");// 将当前工程工作目录设置为根目录

	umask(0);// umask设置为0 确保将来进程有最大的文件操作权限


	// 关闭所有文件描述符
	// 需要动态获取这个进程最多打开文件个数
	int i = 0;
	for(i = 0;i < sysconf(OPEN_MAX) ;i++)
	{

		close(i);

	}// 这里也关闭了 文件描述符为 0  1 2 的标准输入标准输出标准错误

	open("/dev/null",O_RDWR);
	// 因为前面把所有的文件都关闭了,所以这一个open对应fd为0,一下类推
	open("/dev/null",O_RDWR);
	open("/dev/null",O_RDWR);

}
结果:
没有明显结果,因为fd为0 1 2 的文件与 /dev/null (回收站)关联了,所以看不见打印信息。
可以用 kill -9  进程ID 来杀死进程

14· 让程序不能被多次运行

实现方法:用一个特定文件(比较古怪,系统中原来是没有的)的存在与否做标志。
具体:程序在执行之前去判断特定文件是否存在,如果存在则标明进程已经在运行,若不存在则标明进程没有运行,然后运行时去创建这个文件。

15· Linux进程间的通信

进程间通信(IPC)是指2个任意进程之间的通信。

同一个进程下,函数之间,源文件之间,通过全局变量和函数参数传递通信。

2个不同进程处于不同地址空间,所以互相通信很困难。

什么样的进程设计成需要进程间通信?大部分都是单进程(但是可以多线程),但是对于复杂大型程序,设计时多为多线程。

Linux内核提供多种进程间通信机制

(1)无名管道 与 有名管道(FIFO)
(2)SystemV IPC:信号量,消息队列,共享内存
(3)socket域套接字
(4)信号

无名管道:
原理:内核维护的一块内存(可以理解为缓冲区),有读端和写端
方法:父进程创建管道后 fork 一个子进程,子进程继承父进程的管道fd,要想保证通信质量,需要在父进程关闭读端,子进程关闭写端,或者反之。
限制:只限于父子进程,半双工
函数:pipe,write,read,close
在这里插入图片描述

有名管道:
原理:内核维护的一块内存,表现形式为一个有名字的文件。
方法:固定一个文件名,2个进程分别使用mkfifo与这个文件名 关联起来。然后分别open打开获取fd,然后一个读一个写。
限制:半双工(但是不限制于父子进程了,任意两个进程都可以)
函数:mkfifo,open,write,read,close
在这里插入图片描述

SystemV IPC 介绍
特点:
(1)系统通过一些专用API来提供SystemV IPC功能
(2)分为:信号量,消息队列,共享内存
(3)实质还是内核提供的公共内存

消息队列:
本质上是一个队列,队列可以理解为FIFO。(尾插尾拿的链表)
工作时,一个进程向队列中放入消息,另一个进程向队列中读出消息。

信号量:
实质就是一个计数器(一个用来计数的变量,可以理解为int a;一个标志)
通过计数值来提供互斥同步

共享内存:
(1)大片内存直接映射(为了解决内存复制后带来的效益低下问题,就将这块物理内存共享)
(2) 类似于LCD显示时间的显存用法

剩下的2类IPC:
信号
域套接字

详情见下节

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 很抱歉,我是AI语言模型,无法提供自己的笔记。但是,我可以为您提供一些关于Linux网络编程的信息。Linux网络编程是指在Linux操作系统上进行网络编程的技术,主要包括socket编程网络协议、网络编程模型等内容。在Linux网络编程中,常用的编程语言有C、C++、Python等。Linux网络编程应用非常广泛,可以用于开发各种网络应用程序,如Web服务器、邮件服务器、FTP服务器等。同时,Linux网络编程也是网络安全领域的重要技术之一,可以用于网络攻防、数据加密等方面。 ### 回答2: Linux网络编程是一门高级语言编程,包括了网络以及套接字的知识,它的目的是让开发者能够在Linux系统下进行网络应用程序的开发与运行。Linux网络编程中,主要涉及到如下的知识: 1.网络协议:网络协议是数据在计算机网络内传输时所必须遵循的规则和约定。网络协议的共同目标是确保数据的可靠传输。 2.套接字:套接字是一种在网络编程中广泛使用的编程接口,它允许从一个进程向另一个进程通信。通过套接字的编程,可以实现网络上的客户端和服务器端的通信。 3.套接字选项:在套接字编程中,选项提供了一些可选项来控制套接字的行为。例如,可以使用SO_REUSEADDR选项来允许相同的IP地址和端口被多个套接字所使用,或者使用SO_LINGER选项来控制套接字在关闭时的行为。 4.网络编程的主要函数:对于网络编程而言,大多数使用的函数都是socket编程或一些与之相关的函数。如socket、bind、listen、accept、connect、send、recv等。 5.多线程编程和select函数:在网络编程中,常常需要使用多线程编程来同时处理多个套接字,使程序具有高并发性。而select函数可以在一个线程中监听多个套接字的I/O事件,从而优化服务器的性能和响应速度。 6.网络编程的实际应用网络编程在实际应用中,可以实现许多有趣的功能。例如,可以创建简单的聊天程序、实现网络文件传输、远程控制、实现P2P通信等。 总之,Linux网络编程是一种非常重要的技术,要学习并掌握这门技术,需要掌握网络协议、套接字、多线程编程等基础知识。掌握这些知识后,开发者可以根据实际需求,灵活地使用网络编程技术来实现各种基于网络应用程序。 ### 回答3: Linux网络编程在现代软件开发中扮演着非常重要的角色,这是因为它是一种跨平台的操作系统,并且为开发人员提供了良好的网络编程接口。以下是一些重要的技术和笔记: 1. 套接字(socket)编程—— 在Linux环境中,套接字是网络编程的关键要素。它被用于实现客户端/服务器应用程序中的通信,例如Web服务器和聊天室应用程序。在编写套接字程序时,必须使用包括bind,listen和accept等操作来处理连接请求。 2. 网络协议—— Linux支持各种网络协议,例如TCP/IP,UDP,ICMP,ARP和RIP等。其中TCP/IP是最常用的网络协议,因为它可靠且易于使用,在开发网络应用程序时需要具备其相关知识,例如TCP连接管理和协议数据包的格式化。 3. 多线程编程—— 在Linux环境中,多线程编程是一种非常重要的技术,可以同时处理多个网络请求,以提高应用程序的性能。通常使用POSIX线程库(pthread)来实现多线程编程,并使用同步和互斥机制来管理线程访问共享变量的冲突。 4. 网络安全—— 网络安全是Linux网络编程的一个重要方面,因为网络应用程序通常需要保护敏感数据和隐私信息。开发人员必须学习诸如SSL和TLS等加密协议,以确保数据传输的安全性。 总结来说,在Linux环境下进行网络编程需要熟悉套接字编程网络协议、多线程编程网络安全等技术。这些技术的结合可以实现高效的网络应用程序,并提高用户体验。在掌握这些技术后,开发人员可以将网络编程应用于Web服务器、聊天室应用程序、数据存储器等各种应用程序

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值