READMELinux系统编程必读:本专栏内容提要以及系统调用接口总结
Posted 快乐江湖
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了READMELinux系统编程必读:本专栏内容提要以及系统调用接口总结相关的知识,希望对你有一定的参考价值。
前言
本专栏是Linux系统编程学习笔记,内容主要是Linux的认识,命令,进程,IPC,信号,文件和多线程等,点击标题可进行跳转
- 第一部分:主要是该篇博客涉及到的核心知识点
- 第二部分:Linux系统编程中会涉及到大量系统调用,所以会以思维导图的方式总结
- 第三部分:将博客中重要的代码操作拿出来,方便复习,练习
第一部分:博客知识点
(1)基础篇
1:Linux系统编程1:Linux中使用率最高的一些命令
- 命令
ls
,cd
,touch
,mkdir
,rm
,cp
,mv
,cat
,grep
,tar
,less
是读者必须必须要掌握的,他们的各种参数一定要滚瓜烂熟,因为日后他们的使用率几乎高达80% - 掌握如何在Linux中添加用户及设置用户密码
- 理解Linux文件结构
- 理解相对路径与绝对路径
Linux系统编程2:详解Linux中的权限问题
- Linux中的超级用户和普通用户
- su和sudo的区别
- Linux中的权限管理
- 权限的两种表示方法:8进制表示法字符表示法
- 使用chmod修改权限
- 目录的读写还有执行权限如何理解
- 使用chown更改文件拥有者,使用chgrp更改文件所属组
- 理解umask并会用umask设置默认权限
- 理解粘滞位
Linux系统编程3:基础篇之详解Linux软件包管理器yum
此篇博客的内容较为简单,但是很重要——如何在Linux中安装软件,需要大家掌握yum的一些常用用法
(2)入门篇
Linux系统编程4:入门篇之最强编辑器vim的使用攻略
- vim编辑器的三种模式
- vim基本操作
Linux系统编程5:Linux系统编程5:入门篇之在Linux下观察C/C++程序编译过程 && gcc/g++使用详解
- 在Linux下体会C语言文件的编译过程
- 掌握gcc和g++
- 了解函数库
Linux系统编程7:入门篇之Linux项目自动化构建工具-Make/Makefile的超强使用指南
- 学会使用makefile
(3)进程入门
Linux系统编程9:进程入门之操作系统为什么这么重要以及它是如何实现管理的
- 理解操作系统的作用
- 明白系统调用接口和库的关系
Linux系统编程10:进程入门之系统编程中最重要的概念之进程&&进程的相关操作&&使用fork创建进程
- 操作系统是如何管理进程的
- PCB与task_struct的关系
- 什么是进程
- 掌握系统调用接口fork
- fork为什么有两个返回值
Linux系统编程11:进程入门之详细阐述进程的一些状态&&区分僵尸状态和孤儿状态&&动图演示
- 进程的一些状态的理解
- 什么是僵尸进程和孤儿进程
Linux系统编程12:进程入门之进程的优先级及PR和NI&&如何修改进程优先级
- 如何理解进程的优先级
- PR和NI是什么
Linux系统编程13:进程入门之Linux中的环境变量的概念及其相关命令(export;env等)&&main函数的参数
- 环境变量的理解
- 如何查看和设置环境变量
- main函数的三个参数掌握
- 环境变量全局属性
Linux系统编程14:进程入门之Linux进程中非常重要的概念之进程地址空间-原来我们看到的地址全部是虚拟的
- C/C++内存空间复习
- 深刻理解进程地址空间
- 页表的作用
- 虚拟内存和物理内存
Linux系统编程15:进程控制之如何创建进程和写时拷贝技术
- 对于写时拷贝的理解
Linux系统编程16:进程控制之进程终止以及终止进程的三种情况
- 进程退出时的三种情况
- exit的return的区别
- _exit和exit的区别
Linux系统编程17:进程控制之进程等待&&为什么进程需要被等待&wait方法和waitpid方法&&阻塞和非阻塞等待
- 进程为什么需要被等待
- 阻塞式等待和非阻塞式等待的区别
- wait方法
- waitpid方法的第二个参数statuts的理解,它是怎样获取到退出码的,以及低16位的变化情况
Linux系统编程18:超详解进程程序替换&exec函数的一些用法
- 理解进程程序替换
- 6个进程程序替换的接口的掌握
- 重点理解参数的一些意义
Linux系统编程19:基础IO之了解Linux中的标准输入和输出以及相关的系统调用接口(如write,read等)
- 理解标准输入,标准输出和标准错误
- 掌握open,write,read和close的用法
Linux系统编程20:基础IO之从内核代码深刻理解Linux是如何管理文件及文件描述符的本质是什么
- 深刻理解文件描述符fd
- 0,1,2号文件都代表什么
- 从关闭1号文件角度理解重定向
- 从内核角度理解操作系统如何管理文件
- 为什么说一切皆文件
Linux系统编程21:基础IO之全缓冲和行缓冲的区别及深刻理解缓冲区及其作用
- 全缓冲和行缓冲的区别
- 理解C语言提供的用户级缓冲区
Linux系统编程22:基础IO之掌握重定向的本质和使用dup2完成重定向
- 掌握重定向的本质
- 使用dup2完成重定向
Linux系统编程23:基础IO之了解硬盘物理和逻辑结构及明白inode的本质和掌握软硬链接及其区别
- 理解硬盘的物理结构和逻辑结构
- 通过叙述如何查找文件,创建文件,删除文件依次达到对inode和block的理解
- 掌握软硬链接的本质及其他们的区别
Linux系统编程24:基础IO之在Linux下深刻理解C语言中的动静态库以及头文件和库的关系
- 深刻理解动态库和静态库的区别
- 明白库与头文件的关系
Linux系统编程26:进程间通信之进程间通信的基本概念
- 明白我们是怎样给别人提供库的
- 在静态库中如何打包.o文件,如何将头文件和库封装在一个文件中,以及编译时的-I,-L,-l三个参数头代表什么意思
- 在动态库中编译时加入的选项和打包时用的选项,以及最终编译时如何将动态库添加到动态库的环境变量里面
Linux系统编程27:进程间通信之管道的基本概念和匿名管道与命名管道及管道特性
- 进程间通信的本质
Linux系统编程27:基础IO之亲自实现一个动静态库
- 理解管道是什么
- 理解管道的四大特性
- 使用管道完成进程间的通信
- 匿名管道和命名管道的区别
Linux系统编程28:进程间通信之共享内存和相关通信接口(ftok,shmget,shmctl,shmat,shmdt)
- 理解管道和共享内存的区别
- 掌握共享内存系列的接口的用法
Linux系统编程29:进程信号之什么是信号及signal函数
- 信号的处理动作都有哪些
- 掌握signal函数的用法,理解其形参及返回值的含义
Linux系统编程30:进程信号之产生信号的四种方式(Core Dump,kill,raise)
- 四种产生信号的方式及其特点
- 了解core dump
- 了解SIGALRM信号
Linux系统编程31:进程信号之什么是信号的阻塞及相关术语(递达,未决,pending位图,handler位图)
- 信号相关术语:未决,阻塞,递达
- 信号在内核中的表示:pending位图,block的位图的深刻理解
Linux系统编程32:进程信号之详解信号集操作函数(sigset_t ,sigpending,sigprocmask)
- 了解sigset_t类型
- 掌握信号集操作函数的用法
Linux系统编程33:进程信号之详解信号的捕捉过程,用户态和内核态及其切换,sigaction和signal
- 理解用户态和内核态
- 信号是什么是处理和捕捉的——详细叙述信号捕捉过程
Linux系统编程34:进程信号之可重入函数,volatile关键字的作用和SIGHLD
- 理解可重入函数
- 理解volatile关键字的作用
- 如何使用SIGCHLD信号清理僵尸进程
Linux系统编程35:多线程之如何理解Linux中的线程以及轻量级进程LWP
- 理解Linux中的线程
- 理解进程和线程的关系
- 理解LWP
- 线程的优缺点
Linux系统编程36:多线程之线程控制之pthread线程库(线程创建,终止,等待和分离)
- 掌握线程创建,终止,,等待和分离的pthread库函数
- 深化对Linux线程的理解
Linux系统编程37:多线程之什么是临界区和临界资源以及如何使用mutex互斥锁
- 理解临界区和临界资源
- 理解互斥锁的作用
- 理解互斥锁的实现原理
- 可重入函数与线程安全
- 死锁相关
Linux系统编程38:多线程之什么是线程同步以及条件变量函数
- 线程的同步和互斥的理解
- 掌握条件变量函数的使用
Linux系统编程41:多线程之线程池的概念及实现
- 理解线程池,亲自实现线程池
- 线程池概念相关的优缺点
第二部分:涉及的系统调用命令总结
(1)进程部分
(2)基础IO部分
(3)进程间通信部分
(4)进程信号部分
(5)多线程部分
第三部分:重要代码
1:理解fork的作用
#include <stdio.h>
#include <unistd.h>
int main()
{
prinf("还没有执行fork函数的本进程为:%d\\n",getpid());
pid_t=fork();//其返回值是pid类型的
sleep(1);
if(ret>0)//父进程返回的是子进程ID
{
while(1)
{
printf("----------------------------------------------------------------\\n");
printf("我是父进程,我的id是:%d,我的孩子id是%d\\n",getpid(),ret);
sleep(1);
}
}
else if(ret==0)//子进程fork返回值是0
{
while(1)
{
printf("我是子进程,我的id是%d,我的父亲id是%d\\n",getpid(),getppid());
sleep(1);
}
}
else
printf("进程创建失败\\n");
sleep(1);
return 0;
}
2:理解僵尸状态
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
// printf("还没执行fork函数时的本进程为:%d\\n",getpid());
pid_t ret=fork();//其返回值类型是pid_t型的
sleep(1);
if(ret>0)//父进程返回的是子进程ID
{
while(1)
{
printf("----------------------------------------------------\\n");
printf("父进程一直在运行\\n");
sleep(1);
}
}
else if(ret==0)//子进程fork返回是0
{
int count=0;
while(count<=10)
{
printf("子进程已经运行了%d秒\\n",count+=1);
sleep(1);
}
exit(0);//让子进程运行10s
}
else
printf("进程创建失败\\n");
sleep(1);
return 0;
}
3:理解进程等待及waitpid第二个参数
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
pid_t ret=fork();//其返回值类型是pid_t型的
sleep(1);
if(ret>0)//父进程返回的是子进程ID
{
printf("父进程正在等待子进程死亡\\n");
int st=0;
pid_t rec=waitpid(ret,&st,0);//阻塞
if(rec==ret)//如果返回值是子进程id,等待成功
{
printf("等待成功\\n");
if(WIFEXITED(st))//如果为真,正常退出
{
printf("正常退出且退出码为%d\\n",WEXITSTATUS(st));
}
else
{
printf("异常退出,信号值为%d\\n",st&0x7f);
}
}
else
{
printf("等待失败\\n");
exit(0);
}
}
else if(ret==0)//子进程fork返回是0
{
int count=1;
while(count<=10)
{
printf("子进程[%d]已经运行了%d秒\\n",getpid(),count);
count++;
sleep(1);
}
exit(3);
}
else
printf("进程创建失败\\n");
sleep(1);
return 0;
}
4:理解进程程序替换
//myprocess.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
int count=0;
while(count<5)
{
printf("Hello World\\n");
sleep(1);
count++;
}
printf("%s\\n",getenv("myenv"));
return 0;
}
//test.c
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
char* env[]={"myenv=you_can_see_this_env",NULL};
printf("替换函数前\\n");
execle("./myprocess.exe","myprocess.exe",NULL,env);
printf("替换函数后\\n");
}
5:理解文件描述符
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
int main()
{
int fd1=open("log1.txt",O_WRONLY);//打开错误
int fd2=open("log2.txt",O_WRONLY|O_CREAT);//打开成功
int fd3=open("log3.txt",O_WRONLY|O_CREAT);//打开成功
int fd4=open("log4.txt",O_WRONLY|O_CREAT);//打开成功
int fd5=open("log5.txt",O_WRONLY);//打开错误
printf("%d\\n",fd1);
printf("%d\\n",fd2);
printf("%d\\n",fd3);
printf("%d\\n",fd4);
printf("%d\\n",fd5);
}
6:理解匿名管道
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
int main()
{
int pipefd[2]={0};
pipe(pipefd);
pid_t id=fork();
if(id==0)//child
{
close(pipefd[0]);
const char* msg="This is the data that the child process wrote";
while(1)
{
write(pipefd[1],msg,strlen(msg));
sleep(1);
}
}
else//father
{
close(pipefd[1]);
char buffer[64];
while(1)
{
ssize_t ret=read(pipefd[0],buffer,sizeof(buffer)-1);
if(ret>0)//判断是否读到
{
buffer[ret]='\\0';//加上结束标志,便于输出
printf("The father process got the information:%s\\n",buffer);
}
}
}
return 0;
}
7:理解命名管道
server.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
umask(0);//屏蔽命令行umask干扰
if(mkfifo("./fifo",0666)==-1)//如果mkfifo返回值是-1,创建失败
{
perror("打开失败");
return 1;
}
int fd=open("fifo",O_RDONLY);//服务端以只读的方式打开管道文件
if(fd>=0)
{
char buffer[64];
while(1)
{
printf("客户端正在接受消息\\n");
printf("############################\\n");
ssize_t ret=专栏必读王道考研408计算机网络+网络编程万字笔记题目题型总结注意事项目录导航和思维导图
专栏必读王道考研408操作系统+Linux系统编程万字笔记题目题型总结注意事项目录导航和思维导图