本文是牛客网Linux 高并发服务器开发视频教程的笔记
使用ssh在widows中控制Linux系统,使用vscode控制代码
使用g++编译
静态库与动态库的制作、区别
makefile文件操作就是指定所有源文件的编译顺序,因为一个正式的项目会有很多很多源文件,不可能一个个的手动g++,而且各种文件的编译可能还有先后关系,所有要有一个专门的东西来确定编译顺序和编译关系,这个命令就是make。makefile文件
编译时 -g
标准c库io的实现是调用Linux本身的文件操作方式,这种涉及到内存与硬盘的交互的,在不同的平台都可以使用标准c库实现,但是c库回去调用不同平台对应的方法。c库对于文件操作是有缓冲区的存在的,对文件的操作会先对缓冲区操作,最后一下写进磁盘,因此一定要特别注意flush命令的使用
使用open()打开文件,如果打开成功则返回文件描述符,如果打开失败则返回最近的错误码errno,errno是linux内置的错误号。可以通过perror查看erron对应的错误描述。
使用open()也可以创建一个新的文件,在open函数中多一个O_CREAT参数即可
当一个文件被open函数打开后可以通过read和write函数进行读写操作
下面的代码是将一个文件中的内容复制到一个本来不存在的文件中:
#include
#include
#include
#include
#include
using namespace std;
int main()
{
//1、读取待复制的文件
int srcfd=open("/home/lanpangzi/Desktop/Linux/lession02/test01.cpp",O_RDONLY);
if(srcfd==-1){
perror("open");
return -1;
}
printf("文件打开成功\n");
//2、创建一个待粘贴的新的空文件,用来写入
int targetfd= open("cpy.cpp",O_WRONLY|O_CREAT,0664);
if(targetfd==-1){
perror("open");
return -1;
}
printf("文件创建成功\n");
//3、循环读写将文件完全拷贝进去
char buff[1024]{};
int read_re = 0;
while((read_re=read(srcfd,buff,sizeof(buff)))>0){
write(targetfd, buff,read_re);
}
printf("文件复制成功\n");
//4、关闭所有打开的文件
close(srcfd);
close(targetfd);
printf("文件关闭成功\n");
return 0;
}
子进程注意需要使用wait()进行回收,否则容易产生僵尸进程
#include
#include
#include
int main(){
printf("公共段1\n"); //这一句只会执行两遍
// 创建子进程
pid_t n_pid = fork(); // fork之后的语句父子进程都会执行
printf("公共段2\n"); //这一句会执行两遍
// 原来的父进程和新创建的子进程pid不同,通过判断n_pid来判断当前是父进程还是子进程
if(n_pid>0){
printf("当前是父进程!\n");
printf("当前进程的pid: %d, 当前进程的父进程pid: %d\n", getpid(),getppid());
}
else if(n_pid==0){
printf("当前是子进程!\n");
printf("当前进程的pid: %d, 当前进程的父进程pid: %d\n", getpid(),getppid());
}
printf("卧槽真牛逼!\n"); //这一句会执行两遍
return 0;
}
GDB只能跟踪一个进程,但是可以在fork之前设置GDB调试工具是跟踪父进程还是跟踪子进程,以及在跟踪这个进程时另一个进程的状态
使用execl() 函数可以直接跳出当前程序直接去执行其他的程序,exec函数族是几个长得长不多的函数,功能也都是调用一个程序,只是参数传递方式或环境变量设置不同
使用匿名pipe管道进行通信
#include
#include
#include
#include
int main(){
// 创建管道标识,用于接收但会的两个文件描述符
// pipefd[0]->读取pipefd[1]->写入
int pipefd[2];
// 创建管道,返回值用来判断是否创建成功
int ret = pipe(pipefd);
if(ret==-1){
perror("pipe");
exit(0);
}
pid_t pid = fork();
if(pid>0){
// 父进程,向管道中写入信息
char * str = "我是父进程写入的信息";
char buf[1024]={0};
while (1)
{
read(pipefd[0],buf,sizeof(buf));
printf("这里是父进程,读取的信息为:%s\n",buf);
write(pipefd[1],str,strlen(str));
printf("这里是父进程, pid:%d,正在写入文件\n", getpid());
sleep(1);
}
}
else{
// 子进程
// 从管道中读取信息
char * str = "我是子进程写入的信息";
char buf[1024]={0};
while (1)
{
write(pipefd[1],str,strlen(str));
printf("这里是子进程, pid:%d,正在写入文件\n", getpid());
sleep(1);
read(pipefd[0],buf,sizeof(buf));
printf("这里是子进程,读取的信息为:%s\n",buf);
}
}
return 0;
}
使用有名管道 FIFO进行通信
写端:
#include
#include
#include
#include
#include
#include
#include
int main()
{
// 创建之前需要先判断文件是否已经存在
int ret = access("fifo1",F_OK);
if(ret==-1){
// 如果不存在则创建管道
ret = mkfifo("fifo1",0664);
if (ret==-1){
perror("fifo");
exit(0);
}
}
//打开管道准备写入
int fd=open("fifo1",O_WRONLY);
if(fd==-1){
perror("open");
exit(0);
}
for(int i=0;i<100;i++){
char buf[1024];
sprintf(buf, "hello, %d\n", i);
printf("write data : %s\n", buf);
write(fd, buf, strlen(buf));
}
close(fd);
return 0;
}
读端:
#include
#include
#include
#include
#include
#include
#include
int main()
{
int fd = open("fifo1",O_RDONLY);
if(fd==-1){
perror("read");
exit(0);
}
while(1){
char buf[1024]={0};
int len = read(fd,buf,sizeof(buf));
if(len==0){
printf("写端断开连接\n");
break;
}
printf("read buf: %s\n", buf);
}
return 0;
}