牛客C++笔记——linux多进程开发

C++ 多进程编程 需要注意的是,虽然 POSIX 标准只定义了两个用户自定义信号,但某些操作系统或特定的运行时库可能会提供更多的用户自定义信号,超出了 POSIX 标准的范围。这些信号的设计目的是为了给开发人员提供一种扩展的机制,可以在程序中使用自定义的信号进行特定的处理或通信。使用信号来通知子进程终止,并给子进程执行清理操作的机会,可以确保程序在退出时保持良好的状态。通过使用SIGTERM信号,父进程可以优雅地通知子进程要终止,并给子进程一个机会来清理资源和执行必要的关闭操作,避免了突然终止带来的资源泄漏问题。 阅读详情

Linux多进程开发

进程概述

程序和进程

  1. 程序是包含一些机器语言、程序入口、数据、共享库和链接库的文件,用来描述如何在运行时候创建一个进程。
  2. 进程就是正在运行的程序的实例 ,是内核定义的抽象的实体,是操作系统的基本分配单元(占用内存和cpu)、执行单元, 由用户内存空间和一系列内核数据结构组成
  3. 程序就是文件,占用磁盘,一个程序文件可以创建多个进程

单道、多道程序设计

  1. 单道,cpu中只有一个程序在运行
  2. 多道,通过管理程序控制,使得cpu同时穿插运行多个程序,宏观上看同时运行,微观上还是一时刻运行一个,提高cpu利用率。

时间片

  1. 时间片是操作系统内核为进程调度分配的一段cpu时间,一个cpu上穿插运行着多个进程,每个进程占一定的时间片。
  2. 时间片也不能随便切,很小的话利用率也不一定高
  3. cpu其实在一个时刻都只能运行一个指令,只是切片了,穿插着人的层面看来同时运行

并行和并发

  1. 并行,同一时刻,多条指令在多个处理器上同时运行(两队人同时使用两台咖啡机)
  2. 并发,cpu其实在一个时刻都只能运行一个指令,只是切片了,穿插着运行,人的层面看来同时运行(两队人交替使用一台咖啡机)

进程控制块(PCB)

  1. 为了管理每个进程,操作系统内核会给每个进程分配一个PCB,存放着这个进程的一些信息,在内核中是一个结构体,放在内核区中
  2. 信息包括:进程id(唯一,非负整数)、进程状态、cpu时间、一些寄存器数据、文件描述符表、当前工作路径、描述终端控制的信息、用户id和组id、资源上限等

进程状态

  1. 三态模型
    (1) 就绪态:操作系统为进程分配到除cpu外的各项资源之后的状态
    (2)运行态:操作系统为进程分配到cpu资源之后,就进入运行态,如果进程的一个时间片执行完之后就转换成就绪态。
    (3)阻塞态:如果一个进程sleep或者等待用户,就是停住了,就是阻塞态,阻塞结束后进入就绪态
  2. 五态模型:就是在三态模型之外还有新建态、终止态
    (1) 新建态:就是进程刚刚创建,还未进入就绪队列,就是新建态
    (2) 终止态:进程执行完毕、遇到错误退出、被操作系统终止、被其他有权终止的进程终止掉,就进入终止态 ,进入终止态后,等待操作系统来处理删除进程。

进程相关指令

ps aux 或者 ps ajx
# a:显示终端上的所有进程
# u:显示进程的详细信息
# x:显示没有控制终端的进程
# j:列出与作业控制相关的信息

PID:进程的ID,,整数,范围是0~36767,进程号唯一,终止后会重新分配给其他用
PPID: 父进程的ID
PGID:进程组的ID(几个进程一个组成进程组)
SID:会话的ID(几个进程组组成一个会话)
TTY:进程所处的终端
STAT的参数意义
TOP命令

在这里插入图片描述

进程号

  1. 每个进程都有一个号来标识,唯一,被删除后会分配给其他用
  2. 任何进程(除init进程)之外,都是由另一个进程创建,叫父进程,终端也是一个进程,终端中运行一个程序,那他就创建了一个进程
  3. 父进程需要负责回收子进程的资源
  4. 每个进程结束后都会自己释放用户空间,但是内核区需要父进程来释放

进程创建

  1. 使用man fork可以查看fork的文档
  2. 使用:
    unistd.h为Linux/Unix系统中内置头文件,包含了许多系统服务的函数原型,例如read函数、write函数和getpid函数等。其作用相当于windows操作系统的"windows.h",是操作系统为用户提供的统一API接口,方便调用系统提供的一些服务。
#include <sys/types.h>
#include <unistd.h>
//pid_t fork(void);
//返回值:
//	成功:子进程中返回0,父进程中返回子进程ID
//	失败:返回-1,失败原因——1.进程数达到上限,2.系统内存不足
int main(){
pid_t pid = fork();//进程从这里开始出现分支
if(pid > 0) printf("这是父进程会执行的代码");
if(pid == 0) printf("这是子进程会执行的代码");
printf("这是父进进程和子进程都会执行的代码");
}
  1. 父进程创建子进程之后,用户内存空间是拷贝了一份过去的,所以一开始它们拥有的值一样,但后续操作中,两个进程之间互不影响,他们空间是独立的。
  2. 上面说的拷贝,不是创建完就新开辟一个原样的物理内存空间,这样有浪费,他是写时拷贝
  3. 写时拷贝,就是刚创建时候,子进程和父进程其实还是映射着同一个物理内存地址的,但一个进程对这个地方进行写操作时候,才会新开辟一个物理内存空间。这样的目的是为了降低内存消耗和拷贝内存的时间
  4. 创建子进程之后,内核区也是拷贝过去的,里面除了进程管理块(PCB)里面的进程号(pid)东西不一样,其他比如文件描述符那些是一样的
    在这里插入图片描述
    在这里插入图片描述

GDB调试多进程

在这里插入图片描述

exec函数族

  1. exec族函数是用来在一个程序中再启动一个可执行程序,取代原来的进程中的内容,用户区的数据被取代
  2. 如果启动成功,原来的进程已经被取代了,也就没有返回一说了,如果启动失败,返回-1,原进程继续往下执行
#include <unistd.h>
int execl(const char *path, const char *arg, ...);
//path;可执行程序的路径
//arg:可执行程序的参数,参数需要以null结尾(哨兵)
//返回值:只有调用失败的时候才会返回-1,其他没有
  1. 举例
    hello程序,编译生成hello可执行程序
#include <unistd.h>
#include <stdio.h>
int main(){
	printf("hello");
}

调用程序

#include <unistd.h>
#include <stdio.h>
int main(){
    pid_t pid = fork();
    if(pid > 0) 
        printf("father process");
    else{
        execl("hello", "hello", NULL);//第一个为路径,后面的为参数,第一个参数得填,其实没什么用,参数需要以NULL结尾
        printf("original child process\n");
    }
}
  1. 也可用用来执行linux的一些系统命令,它们其实也是可执行程序,比如ps aux、ls等等,
    通过whic ps 就可以查看到ps在哪
    在这里插入图片描述
execl("/bin/ps","ps","aux",NULL)
  1. execlp
    这个相比于excel,他可以去环境变量里面寻找可执行程序,比如就可以这样用
execlp(("ps","ps","aux",NULL);

进程控制

进程退出

  1. _exit()是linux的库函数
  2. exit()是c库函数
    在这里插入图片描述
#include <stdlib.h>
void exit(int status);//这个是c库的函数,status是设置要返回的退出状态
#include <unistd.h>
void _exit(int status);//这个是linux的函数,status是设置要返回的退出状态

孤儿进程

  1. 父进程提前结束之后,子进程还在运行,那他就叫孤儿进程
  2. 出现这样情况时,孤儿进程就交给init() 进程处理,孤儿进程结束之后,它来回收孤儿的资源
  3. 孤儿进程是没有什么危害的

僵尸进程

  1. 就是进程结束之后,但是父进程没有进行回收释放,他就占用着空间和进程号,它就是一个僵尸进程。
  2. 他都不能被kill -9 杀掉,危害很大,可能导致它占着号,占太多满了后面可能就开不了新进程了。
  3. 如果此时父进程结束,那僵尸进程就会变成孤儿进程
  4. 解决方式就是在父进程中用wait()或者waitpid()得到他的退出状态并彻底清除这个进程。
  5. wait()和waitpid()功能差不多,wait()是阻塞的,调用一次处理一个子进程,waitpid是非阻塞的,并且可以指定等待的进进程号
#include <sys/types.h>
#include <sys/wait.h>

pid_t wait(int *wstatus);
//它会等待任意一个子进程结束,任意一个子进程状态变化之后就去执行释放
//参数:传入一个指针,可以获取到子进程状态
//返回值: 1.返回被释放的进程号,2.没有子进程可以释放了或者调用失败返回-1
pid_t waitpid(pid_t pid, int *wstatus, int options);
//参数:
//	pid:
//		pid > 0: 指定子进程的pid
//		pid = 0:回收当前进程组内的所有子进程
//		pid = -1:回收所有的子进程,相当于wait()
//		pid < -1: 要回收指定进程组的pid的绝对值,回收那个指定进程组中的子进程
// 	*wstatus: 获取子进程结束的状态
// 	options: 0-阻塞,WNOHANG-非阻塞

在这里插入图片描述

在这里插入图片描述

进程间通信(IPC)

基本概念

  1. 进程之间使用的资源是独立的,不能直接去访问其他进程的资源
  2. 但是进程不是孤立的,它们可以进行信息和状态的交互
  3. 进程之间通信的作用:数据传输、通知事件、资源共享、进程控制
    4.这里记录一个概念:进程间资源共享的时候,需要同步,这个同步的概念理解是,比如医院看病,一个人看完另一个再去,这叫同步,俩人一起去看病那叫异步。

Linux进程间通信的方式

在这里插入图片描述

管道

管道(匿名管道)概述

在这里插入图片描述
这上面哪个 | 叫做管道符,他的原理就是在当前终端创建一个管道,连接ls 和 wc 两个进程

  1. 管道是内核空间 中维护的缓冲区,是有限的,不同操作系统不一样
  2. 管道拥有文件的特质:读、写操作,管道的两端对应着文件描述符
  3. 匿名管道没有文件实体,有名管道有文件实体,但是也只是在内存中的,不会在磁盘上有一个实际的文件
  4. 管道是一个字节流,不需要定义通信协议,可以从管道中读取任意大小的数据
  5. 管道传递的数据是顺序的,先进先出
  6. 管道是半双工的,就是同一时刻只能一端发,另外一端收,不能同时刻两边都发都收。
  7. 从管道读取数据时一次性操作,一旦被读走,就从管道中被抛弃了
  8. 匿名管道只能在有公共祖先(父进程与子进程、兄弟进程等)的进程间使用
    在这里插入图片描述
  9. 由于子进程与父进程之间其实是有一样的文件描述符,所以它们之间可以通过文件交换数据,同时,管道又是有文件的特性,所以管道就可以用于进程之间的通信。
  10. 同样由于 上面10说的特性,只有有亲缘关系的进程之间它们才满足这样的条件,所以就是如8所说
    在这里插入图片描述
  11. 管道的数据结构,是环形队列
    在这里插入图片描述

使用匿名管道进行进程间通信

在这里插入图片描述
在这里插入图片描述
子进程和父进程两个都去管道里面读取数据的时候,就是第二种情况,有可能出现自己发的数据自己又去读回来,这样是不对的,所以一般只用第三种情况,一边发一边收,这样比较合适。
在这里插入图片描述

  1. 当管道以阻塞模式运行时候
    读管道:
    管道中有数据:就返回读到的字节数
    管道中无数据:
    管道写端都被完全关闭,那就返回0,相当于读到了文件末尾
    管道写端没有完全关闭,那就是阻塞,直到有数据进来
    写管道:
    管道读端被完全关闭:就会收到一个SIGPIPE信号,进程异常终止
    管道读端没有被完全关闭:
    管道已满:阻塞,直到管道内有空间写入
    管道未满:写入数据,并返回实际写入的字节数

  2. 可以通过fcntl函数设置文件描述符的模式,使他变成非阻塞的,这样管道就是非阻塞的了,当非阻塞的时候,如果没有数据,read返回的就是-1。

有名管道

  1. 匿名管道只能在有关系的进程之间通信
  2. 有名管道(FIFO),也叫命名管道、FIFO文件
  3. 有名管道是以文件形式存在于文件系统中的,在磁盘上能看到文件,但是里面是不存数据的,管道的数据都是在内存中(内核区)的,他的打开方式和打开一个普通文件一样,因此即使无关的的进程也能通过FIFO交换数据
  4. 对他的操作其实就是跟普通文件、匿名管道操作一样,数据读取顺序也是先入先出,FIFO(就是先入先出的意思)
  5. 使用FIFO的进程退出后,FIFO文件继续保存在文件系统中以便以后使用
  6. FIFO是有名字的,不同的进程都可以打开管道进行通信

有名管道的使用

在这里插入图片描述
在这里插入图片描述
一般也是,管道设置成一端只写,另一端只读,这样比较好
在这里插入图片描述

用有名管道实现一个聊天功能

  1. 实现思路,实现半双工
    在这里插入图片描述

内存映射

  1. 内存映射也是一种进程间通信的方式,用内存映射磁盘上面的空间,不同进程映射同一块文件,这样一个进程修改了文件,另一个进程就能相应同步改变
  2. 用内存映射的方式效率比较高的
    在这里插入图片描述

mmp内存映射

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

port的一定要有读权限,才能操作文件,port的权限要小于等于open的权限

munmap释放内存映射

在这里插入图片描述

使用内存映射进行进程间通信

  1. 使用内存映射进行通信,不仅可以在父子进程之间,也可以在不想关的进程之间
    在这里插入图片描述

使用内存映射的注意事项

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

信号

信号基本概念

  1. 信号是linux比较古老的一种通信机制,理解为软件中断,一个进程执行过程中,被另外一个异步的进程中断,转去执行另外一个突发事件。 在这里插入图片描述
    在这里插入图片描述

常见的一些信号

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

信号使用

在这里插入图片描述

kill——给指定进程发送指定信号

在这里插入图片描述
在这里插入图片描述

rase——给当前进程发送指定信号,abort——给当前进程发送终止信号

在这里插入图片描述

alarm函数——设定定时器

在这里插入图片描述
该函数时是不阻塞的
4. alarm测试
在这里插入图片描述
这里时把一秒内的数字都输出到终端,经过执行发现,终端其实超过了一秒才完全输出完数据
在这里插入图片描述
这里的原因时,往终端输出数据是需要花费挺多时间的,并且终端输出的缓冲区也是有限的
这里可以这样操作一下,不直接输出到终端,让他重定向输出的文件中
在这里插入图片描述
这样发现速度超级快,并且文件中数据远远比终端输出的要多,当然这样写文件,也是会花费一些时间的
在这里插入图片描述
程序执行时间其实是由这几部分组成的
在这里插入图片描述

setitimer——设置周期性的定时器

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  1. 具体设置步骤
    在这里插入图片描述

信号捕捉

在这里插入图片描述

  1. signal-函数
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  2. sigaction函数
    他和signal函数都是信号捕捉,这个的功能更多一些,signal是一个特殊标准,更推荐使用sigaction
    在这里插入图片描述

在这里插入图片描述

信号集

放在内核区中

在这里插入图片描述

在这里插入图片描述

信号集操作函数

  1. 这些函数只能操作自己定义的信号集(就是那个结构体)进行一些设置
  2. 在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

调用系统函数使用设置的信号集

  1. 上面提到的信号集操作,是这样的,定义一个信号集结构体之后(sigset_t set),用上面那些函数,可以对修改结构体里面的值,但是修改之后,他还是不能发挥作用的,要发挥作用,就需要调用系统函数,使设置好的信号集生效。
    在这里插入图片描述在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

命令行的一些补充知识

  1. 中运行程序分为前台运行和后台运行
  2. 前台运行的时候,他就是会占用这个终端,此时你在终端输入 命令是没有用的
  3. 后台运行的时候,他会往终端打印信息,但是不会占用终端,你输入命令也是可以用的,通过在运行程序后面加个&号,他就是以后台方式运行
  4. 当程序在后台运行时,输入fg命令,就可以切换到前台

SIGCHLD信号

在这里插入图片描述

共享内存

在这里插入图片描述
在这里插入图片描述

  1. 他的步骤,先创建、再关联、再分离、最后再销毁

共享内存操作函数

在这里插入图片描述

  1. shmget——创建共享内存
    在这里插入图片描述
    在这里插入图片描述
    key参数那里,如果进程1是100,进程2也要设为100,这样他俩才能共享到同一块内存
  2. shmat——将当前进程与共享内存关联
    在这里插入图片描述
  3. shmdt——将共享内存与当前进程分离
    当一个进程结束时,会自动和共享内存分离
    在这里插入图片描述
    一个进程和一个共享内存分离后,就不能再操作这块内存了,也不能再次去关联
  4. shmctl——操作共享内存
    在这里插入图片描述
    设置了IPC_RMID之后,共享内存的key就会变成0,此时只是标记删除,要等所有的进程都解除关联之后,才会被真正释放。

共享内存注意事项

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

使用共享内存进行进程间通信

  1. 写进程:
    在这里插入图片描述

  2. 读进程
    这里读这端,他去获取的共享内存大小不能大于开辟的那边的大小
    3.

查看进程间通信方式和共享内存有关的命令

在这里插入图片描述

消息队列

在这里插入图片描述
在这里插入图片描述
在内核中会开辟出一块空间,是一个存放消息的队列(先进先出),本质是个链表,进程通过获取对应的消息队列id,往队列里面发送或者读取消息,

通过ipcs -q可以查看到目前有的消息队列
在这里插入图片描述
linux中有两种消息队列
在这里插入图片描述

System V

在这里插入图片描述

  1. msggget可以完成消息队列的创建,传入的第一个参数决定着这个消息队列的身份标识,两个进程要想访问同一个消息队列的话,这个值需要一样
  2. 这个值可以通过一个ftok()函数来创建
  3. 消息里面的mtype是消息类型,你发什么类型的消息,就要读什么类型的消息

发送消息
在这里插入图片描述
消息接收
在这里插入图片描述

Posix

在这里插入图片描述

发送消息
在这里插入图片描述

接收消息

在这里插入图片描述
在这里插入图片描述

守护进程

终端

在这里插入图片描述

进程组

在这里插入图片描述

会话

在这里插入图片描述

  1. 进程组的首进程不能创建新的会话

在这里插入图片描述
3. 开启一个终端后,就自动启动一个bash进程,在后台运行,他就会自动生成一个进程组,然后再生成一个会话,他的PID是400,PGID也是400,SID也是400
4. 然后启动了find和wc在后台运行,find的PID是658,那find就又生成一个进程组,进程组号PGID是658,wc和find同在一个进程组中,所以wc的PGID是658
5. 然后启动了sort和uniq在后台运行,sort的PID是660,那sort就又生成一个进程组,进程组号PGID是660,sort和uniq同在一个进程组中,所以uniq的PGID是660
6. 由于658、660和400都是会话400下面的进程组,所以这些里面的进程他们的会话SID都是400
7. 由于一个会话智能又一个前台进程组,所以660在前台,660里面的进程才可以使用终端输入输出,658和400都在后台

守护进程

在这里插入图片描述

守护进程的创建

在这里插入图片描述

  1. 要用子进程去创建新会话的原因:在调用setsid()的时候会直接创建一个新会话,会话的SID为该进程的PID,组PGID也是该进程的PID,如果用的是父进程来创建新会话,由于父进程PID=100是他所在进程组的首进程,进程组的PGID=100,当父进程调用setsid之后,创建的新会话中就会和目前的冲突,所以不能用父进程来创建新会话。
  2. 案例
/* 写一个守护进程,每隔2s获取一下系统时间,将这个时间写入到磁盘文件中。*/
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <signal.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>

void work(int num) {
    // 捕捉到信号之后,获取系统时间,写入磁盘文件
    time_t tm = time(NULL);
    struct tm * loc = localtime(&tm);
    // char buf[1024];

    // sprintf(buf, "%d-%d-%d %d:%d:%d\n",loc->tm_year,loc->tm_mon
    // ,loc->tm_mday, loc->tm_hour, loc->tm_min, loc->tm_sec);

    // printf("%s\n", buf);

    char * str = asctime(loc);
    int fd = open("time.txt", O_RDWR | O_CREAT | O_APPEND, 0664);
    write(fd ,str, strlen(str));
    close(fd);
}

int main() {
    // 1.创建子进程,退出父进程
    pid_t pid = fork();

    if(pid > 0)
        exit(0);
    
    // 2.将子进程重新创建一个会话
    setsid();

    // 3.设置掩码
    umask(022);

    // 4.更改工作目录
    chdir("/home/nowcoder/");

    // 5. 关闭、重定向文件描述符
    int fd = open("/dev/null", O_RDWR);
    dup2(fd, STDIN_FILENO);
    dup2(fd, STDOUT_FILENO);
    dup2(fd, STDERR_FILENO);

    // 6.业务逻辑
    // 捕捉定时信号
    struct sigaction act;
    act.sa_flags = 0;
    act.sa_handler = work;
    sigemptyset(&act.sa_mask);
    sigaction(SIGALRM, &act, NULL);

    struct itimerval val;
    val.it_value.tv_sec = 2;
    val.it_value.tv_usec = 0;
    val.it_interval.tv_sec = 2;
    val.it_interval.tv_usec = 0;

    // 创建定时器
    setitimer(ITIMER_REAL, &val, NULL);

    // 不让进程结束
    while(1)
        sleep(10);
 
    return 0;
}
C++:多进程、多线程 这篇文章详细介绍了多进程与多线程的概念和用法,分析了它们的相同点与不同点,并提供了代码示例,希望对大家有所帮助。 阅读详情

相关推荐

牛客网C++项目-Linux高并发服务器开发之第一章:Linux系统编程入门 学习笔记

自用,不建议阅读,因为内容较为基础且繁杂,更多的是通过观看视频教学留下印象,这篇博文也是为了此后方便查找、补充相关知识点

farewellyi的博客 3465

C++项目实战-多进程(一篇文章)

程序和进程的基本概念 单道程序设计和多道程序设计 并行和并发 进程控制块PCB 进程常用的命令 环境变量 环境变量操作函数

weixin_46120107的博客 1万+

【并发编程二】c++创建子进程CreateProcess()

CreatProcess()需要若干参数来指定新进程的运行方式,但实际使用中多半参数都是用不到的,可以设置为NULL。int main(int argc, char*argv[])_argc 是整型变量,argv 是指向字符串的指针数组。进程相关的API

junxuezheng的博客 9395

c++多进程编程

c++多进程编程 介绍 进程:进程是一个正在执行的程序,是向CPU申请资源的,进程之间数据相互独立,一个进程至少有一个线程。 线程:线程是进程中的单一的顺序控制流程也可以叫做最小控制单元,线程是进程中执行单元,开启一个线程比开启一个进程更加节省资源。 多线程:多线程是多任务处理的一种特殊形式,多任务处理允许让电脑同时运行两个或两个以上的程序。一般情况下,两种类型的多任务处理:基于进程和基于线程。...

Wandering的博客 2万+

C++ 后端开发路线——愿我踩过的坑,你可以绕着走

阶段0书籍推荐在这个从零起步的阶段我还是建议先从C语言开始学起,不建议直接从C++开始学起,这里我推荐几本我看过的书。《C Primer Plus 第六版》个人非常推荐这本书入门,我入门的时候就是看这本书的第五版,前前后后看了三遍,这三遍不仅仅是读完一遍再读一遍,而是有技巧性的。第一遍可以粗略的读,大概把语法都了解,一些不理解的地方可以自己手动实现一下。第二遍就要精读,课...

编程与实战的博客 3797

牛客面经整理:C++高频面试题

1.语言基础(C++) (1) 指针和引用的区别 (2) 堆和栈的区别 (3) new和delete是如何实现的,new 与 malloc的异同处 (4) C和C++的区别 (5) C++、Java的联系与区别,包括语言特性、垃圾回收、应用场景等(java的垃圾回收机制) (6) Struct和class的区别 (7) define 和const的区别(编译阶段、安全性、内存占用等) (8) 在...

沉迷单车的追风少年 2487

牛客C++项目笔记——第二章linux多进程开发

exec 函数族的作用是根据指定的文件名找到可执行文件,并用它来取代调用进程的内容,换句话说,就是在调用进程内部执行一个可执行文件。- exec 函数族的函数执行成功后不会返回,因为调用进程的实体,包括代码段,数据段和堆栈等都已经被新的内容取代,只留下进程 ID 等一些表面上的信息仍保持原样,颇有些神似“三十六计”中的“金蝉脱壳”。看上去还是旧的躯壳,却已经注入了新的灵魂。只有调用失败了,它们才会返回 -1,从原程序的调用点接着往下执行。

qq_45364037的博客 567

linux下的C\C++多进程多线程编程实例详解

主要介绍了linux下的CC++多进程多线程编程实例详解的相关资料,需要的朋友可以参考下

Linux高并发服务器开发---笔记1(环境搭建、系统编程、多进程)

0613首先这整个系列笔记属于笔记①:牛客校招冲刺集训营—C++工程师中的第四章笔记。视频课链接: 视频1:Linux高并发服务器开发(40h); 视频2:第4章 项目制作与技能提升(录播)(26h30min); 视频课3: 第5章 高频考点与真题精讲(录播)中的5.10-5.13 项目回顾有个学生的评论: 上个月做了也是这个老师讲得一个2400分钟的webserver课程,但只能实现访问服务器上图片的功能,也没有登录,数据库日志相关的东西,现在又看到这个课程,人麻了,先做这个多好。。。所以直接看这个26h

weixin_38665351的博客 8699

机器视觉/将HIK海康面阵相机连接Halcon软件

本文简述了如何将海康面阵相机连接到Halcon软件中进行实时取图的过程。

Dahe.qu 4866

QGC 转发RTSP流 到RTMP服务器

需求: QGC安卓版在接收摄像机RTSP视频流的时候,需要将视频推送到指定的RTMP服务器。 分析: QGC在处理音视频的时候使用了GStreamer这套框架,本身这套框架是跨平台的,所以无需关系环境,只要想到相应位置,添加对应功能代码,然后配置好安卓端的依赖库即可。 添加位置: GstVideoReceiver.cpp -》start函数负责音视频的流的播放,只需在此处添加上封装好的推流函数即可。 同理在stop中添加停止推流功能。 方便起见,可在界面上配置rtmp的推流地.

qthello 2324

牛客C++笔记——linux多线程开发

C++笔记——多线程开发

qq_42657656的博客 265

LMI线性矩阵不等式之非线性变量处理

​ 如果一个LMI线性矩阵不等式中的某项存在两个矩阵变量相乘,那么称该类情形为非线性矩阵不等式,而要直接求解时很困难的,而且LMI工具箱也无法求解非线性矩阵,所以需要通过变量替换法进行处理。 ​...

Mr.邹的博客 4550

Linux C++服务器项目——多进程

exec函数族的作用是根据指定的文件名找到可执行文件,并用它来取代调用进程的内容,换句话说,就是在调用进程内部执行一个可执行文件。exec函数族的函数执行成功后不会返回,因为调用进程的实体,包括代码段,数据段和堆栈等都已经被新的内容取代,只留下进程ID等一些表面上的信息仍保持原样,颇有些神似"三十六计"中的"金蝉脱壳"。看上去还是旧的躯壳,却已经注入了新的灵魂。只有调用失败了,它们才会返回-1,从原程序的调用点接着往下执行。

程序员,他们想的是什么?他们想的永远都是技术,他们崇尚的也永远都是技术。 1230

sas协议(SAS PL-3)之Zoning功能

1 Zoning overview SAS zoning is implemented by a set of zoning expander devices with zoning enabled that define a zoned portion of a service delivery subsystem (ZPSDS)服务子系统. The zoning expander devices control whether a phy is permitted to participate in

sinat_37817094的博客 1530

【光子 AI】AI Agent 知识体系深度研究报告

从理论基础到前沿应用:全面解析人工智能代理的核心架构、关键技术与发展趋势📅 2026 年 3 月 | 📊 深度研究报告 | 🔬 人工智能领域 | 📈 前沿技术分析**AI Agent(人工智能代理)**是一种能够感知环境、基于所获得的信息做出决策,并执行行动以影响该环境的软件系统。AI Agent 的设计旨在模仿或实现智能行为,它们可以在各种环境中操作,包括物理世界和虚拟空间。随着大语言模型(LLM)技术的突破性进展,AI Agent 正从实验室研究快速走向产业应用。根据 Gartner 发布的《2

AI天才研究院 176

牛客C++项目笔记—第一章linux入门

库文件是计算机上的一类文件,可以简单的把库文件看成一种代码仓库,它提供给使用者一些可以直接拿来用的变量、函数或类。- 库是特殊的一种程序,编写库的程序和编写一般的程序区别不大,只是库不能单独运行。- 库文件有两种,静态库和动态库(共享库),区别是:静态库在程序的链接阶段被复制到了程序中;动态库在链接阶段没有被复制到程序中,而是程序在运行时由系统动态加载到内存中供程序调用。- 库的好处:1.代码保密 2.方便部署和分发。

qq_45364037的博客 444

CST与MATLAB连接设置

打开MATLAB,点击"Set Path"按钮,然后点击"Add Folder"。在CST中,点击"Options"菜单,然后选择"Advanced"选项。在弹出的对话框中,点击"COMSOL"选项卡,并确保"Enable COMSOL"复选框被选中。通过上述步骤和示例代码,你可以开始使用MATLAB与CST进行集成,并根据你的具体需求进行进一步的开发和应用。通过这个简单的示例,你可以开始在MATLAB中与CST进行交互,并根据你的需求进行更复杂的操作,如参数化仿真、优化和数据处理等。

TechPulseZ的博客 1966

Linux C++服务器项目——项目实战2、3(项目代码讲解)

但反过来思考,注册了EPOLLONESHOT事件的socket一旦被某个线程处理完毕,该线程就应该立即重置这个socket 上的EPOLLONESHOT事件,以确保这个socket下一次可读时,其EPOLLIN事件能被触发,进而让其他工作线程有机会继续处理这个socket。状态机的当前状态记录在cur_State变量中。比如一个线程在读取完某个socket 上的数据后开始处理这些数据,而在数据的处理过程中该socket上又有新数据可读(EPOLLIN再次被触发),此时另外一个线程被唤醒来读取这些新的数据。

程序员,他们想的是什么?他们想的永远都是技术,他们崇尚的也永远都是技术。 1146

二、TCP/IP协议之网络层(IP地址的格式、分类、报文格式)

数据报每经过一个路由器,路由器都要重新计算一下首部检验和,若首部未发生变化,则此结果必为 0,于是就保留这个数据报。对于网络号相的设备,无论实际所处的物理位置如何,它们都是处在同一个网络中。在首部的固定部分的后面是一些可选字段,其长度是可变的。IPv4 软件在存储器中维持一个计数器,每产生一个数据报,计数器就加 1,并将此值赋给标识字段。表示数据报在网络中的寿命,英文缩写是 TTL(Time To Live),功能是“跳数限制”。地址的网络号码字段用来标识一个网络,网络号码字段的前几位用来区分。

锦慈的技术博客 185

H3C BGP联盟实验

bgp,bgp联盟,bgp公认团体属性,

一只懒羊羊 970

[项目] Linux高并发服务器

[项目] Linux高并发服务器 杂谈 最近越来越感觉那些教你几小时做个网站啊之类的速成教程对技术学习有着很大危害,在贩卖焦虑的同时给你蛇油(虚伪的万金油),造成自己好像学了挺多的,做的挺好的假象。 这对我来说,属实有些折磨了,因为作为普通人类的我,是很难抵挡住大数据推荐的勾引的。 后来想了想还是找一些相对完整的项目学一下比较好,大一下的时候照着大佬的教程写了一个很水的JSON解析库,从中学到了很多,这种满足感真正令我感到充实。比较遗憾的是,后期没有做足够完整的总结,现在很多细节操作都忘的差不多了。 翻了一

鱼竿钓鱼干 7156

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

牛客Linux高并发服务器开发学习第一天

安装Xshell 7远程连接虚拟机的Ubuntu安装Xftp 7可以传输文件(暂时还没使用)安装VMware Tools可以直接从Windows系统向虚拟机Linux系统拖拽文件实现文件交互。安装CScode可以远程连接Linux系统进行代码的编写。(Windows系统与Linxu系统公钥进行了一系列操作使得CScode直接连接Linux系统不需要输入密码)

jinyang1110的博客 546

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

cpp学习计划

内容包括:✅ 本周完成任务❌ 卡住问题💡 下周优化方向🧩 一条“可写进简历”的技术积累点每完成一个项目 → 立刻写:README(项目架构图 + 性能测试截图)技术博客(例如「我用C++实现了一个高性能HTTP服务器」)

qq_59116228的博客 1632

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

[cpp]Linux系统编程(到进程)

牛客webserver笔记

记忆超差的本人的博客 1915

C/C++服务器开发/后端开发 学习、面试总结 经验分享

C/C++发展方向 后台/服务器 桌面客户端 图形学/游戏/VR/AR 测试开发 网络安全/逆向 嵌入式/物联网 音视频/流媒体/SDK 计算机视觉/机器学习 什么是后端/后台/服务器开发? 经常在各大公司招聘上看到后端、后台、服务器开发等等,有些同学经常被这些名词搞混。 其实这些名词都是相近的,但是也有点区别,这里说说我的理解: 首先一般公司分为前端和后端,前端就是和用户打交道的,负责用良好的视觉效果将数据呈现给用户,广义的前端包括客户端(安卓、IOS)、Web前端、小程序等。 而与之对应的后端则是负

C/C++Linux、音视频、DPDK 5814
上一篇: 解决Y9000K-2070Super在Ubuntu下安装nvidia显卡驱动后黑屏的问题
下一篇: C++笔记——linux系统编程入门
MUCH_WAY
博客等级 码龄8年 25粉丝 26原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值