UNIX_C
文章平均质量分 75
UNIX_C
半只因
这个作者很懒,什么都没留下…
展开
-
UNIXC002 线程的同步 之 mutex锁、条件变量、信号量
1. 可重入函数如果一个函数访问了全部变量,静态局部变量,还有堆里的内容,那么这个函数就是不可重入函数。线程之间是异步的,如果T1,T2都要访问进程数据段的资源(比如T1写,T2读),会造成不确定性。这时的T1,T2对应的函数都是不可重入函数。所以需要用线程同步来解决这种问题。2. 临界资源2.1 临界资源2.2 临界区3. 线程同步的三种方式3.1 mutex互斥锁是一种互斥设备,用来保证共享数据操作的完整性。互斥锁类型的对象标记用来保证在任何时刻,只能有一个线程访问该对象。原创 2021-01-21 15:46:56 · 191 阅读 · 0 评论 -
UNIXC002 线程的创建和终止、汇合和分离
1. 线程的基本概念进程 = 一个资源 + 多个指令执行序列,这多个指令执行序列指的就是线程。进程中的所有线程共享映射表,映射表不会变。pc指针指向的是下一条要执行的指令的位置。有多个指令执行序列,所以pc指针在不断改变右图中,T1、T2是进程中的两个线程,他们共享进程的资源,也有自己的私有资源。每个线程都有一个线程执行函数,私有资源就在函数对应的栈帧里面。函数又共享进程的所有资源,也就是代码段,数据段,堆里面的内容。1.1 线程的好处上图中,左右两个进程里都有各自的三个线程原创 2021-01-20 16:28:09 · 207 阅读 · 0 评论 -
UNIXC002 UDP编程
1. UDP编程模型TCP是基于连接的,而UDP是基于数据包的。所以不要connect(2)建立连接1.1 服务端1.2 客户端2. 系统调用2.1 recvform(2)对方的地址和端口号会被放在 src_addr2.2 sendto(2)3. 代码示例服务端(基于UDP)将客户端请求的字符串转为大写,并回应客户端客户端(基于TCP)向服务端发送字符串,并将服务端返回的结果打印出来# 制作动态库# 1. 将t_net.c编译成与位置无关目标文件$ gcc原创 2021-01-19 18:29:18 · 119 阅读 · 0 评论 -
UNIXC002 TCP并发服务器实现
多进程实现服务器并发图A适合子进程只负责跟客户端的沟通,需要连接描述符就够了。但它层父进程继承了设备描述符和连接描述符,所以直接关闭设备描述符就可以了。t_stdio.h#ifndef T_STDIO_H_#define T_STDIO_H_#include <stdio.h>#define E_MSG(STRING, VAL) do{perror(STRING); return(VAL);}while(0)# endif 网络模块: t_net.h, t_n原创 2021-01-19 16:38:58 · 102 阅读 · 0 评论 -
UNIXC002 TCP代码封装
本篇文章是将之前写的TCP编程基础中的代码封装起来t_stdio.h#ifndef T_STDIO_H_#define T_STDIO_H_#include <stdio.h>#define E_MSG(STRING, VAL) do{perror(STRING); return(VAL);}while(0)# endif 网络模块: t_net.h, t_net.c这部分会打包成动态库t_net.h#ifndef T_NET_H_#define T_NET_H_.原创 2021-01-18 18:44:22 · 164 阅读 · 0 评论 -
UNIXC002 TCP编程基础
1. 科普1. TCP/UDP的优缺点2. 使用场景2. 三次握手2.1 握手过程网上有太多的详解比如 详解 TCP 连接的“ 三次握手 ”与“ 四次挥手 ”上图中seq是TCP报文中的32位确认序号,ack是32位确认序号。第一次连接中,TCP报文中,标记位为SYN,表示“请求建立新连接”,序号seq=100。第二次连接中,TCP报文中,标志位为SYN和ACK,表示“确认客户端的报文seq序号有效,同意创建新连接,序号seq=500,确认序号ack=101(确认方Ack=发起原创 2021-01-18 15:13:45 · 208 阅读 · 0 评论 -
UNIXC002 网络基础
水电费原创 2021-01-12 20:34:55 · 309 阅读 · 0 评论 -
UNIXC002 system v IPC、共享内存
system v IPCsystem v ipcs 分为以下3种类型 $ ipcs# 消息队列------ Message Queues --------key msqid owner perms used-bytes messages # 共享内存------ Shared Memory Segments --------key shmid owner perms bytes原创 2021-01-12 18:39:38 · 124 阅读 · 0 评论 -
UNIXC002 信号集、信号的阻塞
信号集,信号的阻塞未决信号: 未完成的信号,即信号产生了但是没有被处理。比如pending中的二三号信号。信号阻塞: 当信号到达以后,进程不对它做任何处理。比如blocking中搞得三四号信号。每个进程的PCB当中都维护这样两个数组,blocking和pending, 这是种特殊的数组,简称为信号集,每一位只能取值0或1.handle代表对信号的处理, SIG_IGN: 忽略, SIG_DFL: 默认,user define: 自定义上图中:进程对一号信号不阻塞,但一号信号还没有发生(pe原创 2021-01-10 16:41:25 · 135 阅读 · 0 评论 -
UNIXC002 信号的产生、暂停进程
1. 信号的产生的三种方式下面简单介绍下kill(2), raise(3), alarm(2)1.1 kill(2)#include <sys/types.h>#include <signal.h>#include <stdlib.h>int main(int argc, char *argv[]){ // C 库函数 int atoi(const char *str) 把参数 str 所指向的字符串转换为一个整数(类型为 int 型)。原创 2021-01-09 11:37:02 · 151 阅读 · 0 评论 -
UNIXC002 进程间通信 之 信号
信号1. 概念$ kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR111) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM16) SIGS原创 2021-01-11 20:01:36 · 94 阅读 · 0 评论 -
UNIXC002 进程间的通信 之 管道
进程间的通信之管道用户空间和内核空间对32位操作系统而言,它的寻址空间(虚拟存储空间)为4G(2的32次方)。操心系统的核心是内核,独立于普通的应用程序,可以访问受保护的内存空间,也有访问底层硬件设备的所有权限。为了保证用户进程不能直接操作内核,保证内核的安全,操心系统将虚拟空间划分为两部分,一部分为内核空间,一部分为用户空间。针对linux操作系统而言,将最高的1G字节(从虚拟地址0xC0000000到0xFFFFFFFF),供内核使用,称为内核空间,而将较低的3G字节(从虚拟地址0x000000原创 2021-01-08 20:05:07 · 116 阅读 · 0 评论 -
UNIXC002 环境变量
环境变量之前写过一篇博客:UNIXC01 环境变量 主要讲再命令行里操作变量。下面说说如何在进程里操作环境变量。1. 对环境变量的操作的几个库函数每个进程都有一个属于自己的环境变量列表,进程使用这些变量的值去使用系统提供的资源。下面主要说说使用库函数操作进程的环境变量。1.1 getenv1.2 putenv1.3 setenv1.4 unsetenv, clearenv2. 代码示例#include "t_stdio.h"#include <stdlib.h>原创 2021-01-06 23:30:16 · 116 阅读 · 0 评论 -
UNIXC002 exec(3)家族更新进程映像
1. 更新进程映像不便于扩展的意思就是,只能在pid==0的那个位置写子进程执行的代码exec是对execve这个系统调用进行了封装的库函数家族, 下面先介绍execve1.1 execve子进程先继承父进程的映像,然后父进程中execve 用新的进程映像把子进程的印象覆盖掉。即: 拿filename这个程序的代码段,数据段,栈段,堆等覆盖掉从子进程从父进程中继承下来的印象当中的代码段,数据段,栈段,堆等。包括父进程中原有的execve函数也被覆盖掉,子进程中不会执行execve,子进程也原创 2021-01-06 20:11:48 · 135 阅读 · 0 评论 -
UNIXC002 进程资源的回收、孤儿进程和僵尸进程
进程的资源回收进程终止以后,如果父进程不来回收子进程的资源,相当于子进程的用户态已经结束了,但是内核态没有,子进程的PCB还在占用着资源。这个PCD有时被称为进程的僵尸(白白占用系统的内存)。所以在子进程结束以后要及时的回收子进程的僵尸。1. wait1.1 可以使用以下 宏检测进程终止的原因$ man 2 wait.... WIFEXITED(status) returns true if the child terminated normall原创 2020-12-31 19:32:51 · 176 阅读 · 0 评论 -
UNIXC002 进程创建,终止,遗言函数
进程的基础知识1. 程序和进程2. 查看进程信息3. 进程的状态进程的创建1. fork 创建一个子进程通俗的讲,这个函数调用一次但可能"返回两次"。父进程中调用fork,在创建子进程成功的情况下,会在父进程中返回子进程pid,并会在子进程中返回0。如果没有创建成功,只会在父进程中返回-1。2. 代码示例t_stdio.h#ifndef T_STDIO_H_#define T_STDIO_H_#include <stdio.h>#define E_MSG原创 2020-12-29 22:14:15 · 281 阅读 · 0 评论 -
UNIXC001 文件锁
文件锁1. 概念进程A打开一个文件,在内核中产生一个struct_file 类型的结构体变量叫fileA, 进程B打开一个文件,在内核中产生一个struct_file 类型的结构体变量叫fileB. fileA和fileB中有文件的路径,通过文件的路径找到inode,然后就可以通过inode来访问对应的数据块。(上图中fileA、B要访问的inode相同)文件锁分为读锁和写锁,又叫共享锁和互斥锁fileA和fileB同时访问inode, 如果fileA对inode进行写, 而fileB对ino原创 2020-12-26 13:05:34 · 145 阅读 · 0 评论 -
UNIXC001 文件夹操作
文件夹操作$ mkdir test$ ls -ltotal 4drwxrwxr-x 2 moonx moonx 4096 12月 26 09:12 test# 文件夹里x代表可通过的意思$ chmod a-x test$ cd test/bash: cd: test/: Permission denied$ chmod a+x test$ cd test/$ touch fileA fileB$ cd ..$ rm test/fileA# 在文件夹下新建、删除文件或文件夹属于原创 2020-12-26 10:02:04 · 100 阅读 · 0 评论 -
UNIXC001 文件操作 之 文件的元数据
文件的元数据1. 概念2 文件的 数据 和 元数据fileA 是文件的名字,中间是struct_inod 类型的结构体变量,里面主要有有两部分内容,数据块表和元数据每个文件有且仅有一个自己的inod,通过文件的名字fileA就能找到文件的inod,找到文件的inod以后,才能操作文件的元数据,和操作文件的内容。# ls -i 可以查看文件的inod$ ls -i hello 113377290 hello2.1 数据块表数据块表:是一个整型数组,里面有15个元素,每个元素指定原创 2020-12-25 18:03:01 · 640 阅读 · 0 评论 -
UNIXC001 文件操作 之 内存的映射 mmap
物理地址映射到虚拟地址空间mmp 会在物理地址里找一块页框,然后在用虚拟地址空间选一块虚拟(线性地址)地址,然后将这两个内容分别填到页表里,就建立起来里他们之间的映射关系。用户态先通过虚拟地址找到页表,然后再找到对应的物理地址,然后在访问其中的内存,mmp这这个系统调用就是来建立这种关系的文件映射到虚拟地址空间除了将物理地址映射到线性(虚拟)地址空间,还可以将文件映射到虚拟地址空间,那么用户在虚拟地址空间里(也就相当于用户在内存里面),直接对文件的操作可以同步到文件当中。这样就可以一次映射原创 2020-12-22 16:48:55 · 303 阅读 · 1 评论 -
UNIXC001 文件操作 之 文件管理案例
文件的打开和关闭1. 以只读的方式打开文件, 文件名通过argv[1]传递给程序, r_file.ct_file.h#ifndef T_FILE_H#define T_FILE_H#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#endift_stdio.h#ifndef T_STDIO_H_#define T_STDI原创 2020-12-13 19:34:31 · 187 阅读 · 0 评论 -
UNIXC01 文件操作 之 系统调用,文件权限
文件管理open形参位置的那三个点叫可变参数, 这个参数有没有, 有多少个, 类型, 由前面的 flags 决定函数的可变参数可以看出在printf函数中, 前面一个参数中有占位符%s, %d … 时, printf函数就需要第二个参数,第二个参数里的数量和类型取决于前面那个参数中有几个什么类型的占位符。文件描述符文件描述符表项是一个指针数组,struct file类型的对象(files)的地址会放在这个指针数组当中。指针数组的下标就是文件描述符。files会找到文件描述符原创 2020-12-10 20:28:35 · 650 阅读 · 0 评论 -
UNIXC01 内存管理02
获取进程的PID只有知道了进程的pid以后, 才能获取到进城映像的相关信息#include <unistd.h>#include <sys/types.h>#include <unistd.h>pid_t getpid(void);功能: 获取当前进程的pid返回值: 返回当前进程的pid补充:cat /proc/$$/maps #查看当前bash进程的映像文件获取进程的相关信息cat /proc/$进程pid/maps #获取指定原创 2020-12-08 18:09:23 · 213 阅读 · 0 评论 -
UNIXC01 内存管理01
涉及到一些计算机基础知识, 并且我个人觉得这几个知识不是很重要, 就先跳过原创 2020-12-01 14:35:57 · 135 阅读 · 0 评论 -
UNIXC01 错误处理
程序中的错误处理$ main 3 fopen #/return value 如果fopen调用失败返回NULL, 并且errno的值被用来标识错误.... Upon successful completion fopen(), fdopen() and freopen() return a FILE pointer. Otherwise, NULL is returned and errno is set to indicate the error.原创 2020-11-27 19:57:33 · 97 阅读 · 0 评论 -
UNIXC01 动态加载
动态加载对动态库的加载分为自动加载和动态加载两种自动加载程序在开始执行的时候, 将依赖的动态库文件加载到内存中, 再进行函数的链接, 称为自动加载 (之前讲动态库讲过)动态加载程序在执行期间, 需要使用到某个动态库中的文件的时候, 可以向动态链接器发出请求, 请求将动态库文件加载到内存中. 这种行为称为动态加载动态加载API动态链接器为动态库加载提供了相应的API(动态链接器也是一个封装好的库, 下面讲库中提供的四个常用的API)dlopen(3) dlclos原创 2020-11-26 17:19:27 · 201 阅读 · 0 评论 -
UNIXC01 动态库的制作和使用
动态库的制作和使用1. 制作步骤将所有要加入库的源文件编译为目标文件(与位置无关的目标文件(后面讲内存会提到))gcc -c -fPIC add.c mul.c将第一步生成的目标文件打包到动态库文件中gcc -shared -o libp_math.so add.o mul.o使用动态链接库生成可执行文件在解决依赖(把动态库文件放到/usr/lib 或者 /lib下)的前提下直接 gcc main.o -lp_math如果只是改变了 LD_LIBRARY_PATH, 链接原创 2020-11-26 13:34:30 · 153 阅读 · 0 评论 -
UNIXC01 库文件, 静态库的制作和使用
库文件基础什么是函数库?存放函数的仓库就是函数库系统提供了标准库和一些其他的库文件用户也可以自定义函数库根据链接方式的不同, 将函数库分为动态库(共享库)和静态库两种库函数的命名规则动态库命名规则 lib库名.so静态库命名规则 lib库名.a静态库的制作和使用1. 将所有要加入库中的源文件编译为目标文件(gcc -c *.c)2. 将第一步生成的所有目标文件打包为静态库文件(ar -r lib库名.a *.o )3. 使用静态库文件链接生成可执行文件原创 2020-11-25 20:55:12 · 144 阅读 · 0 评论 -
UNIXC01 环境变量
环境变量程序和进程程序是计算机指令的集合, 存储在磁盘空间里, 是静态的.进程是程序执行的实例, 是程序加载到内存里执行的过程的描述, 是动态的程序运行期间称为进程, 程序运行完毕进程结束. 程序运行一次产生一个进程每个进程都维护着一个环境变量列表, 进程可以通过这些变量访问计算机的资源使用pstree查看进程树环境变量bash 进程有两种变量,自定义变量和环境变量可以被子进程继承的变量称为环境变量进程私有的变量称为自定义变量, 不能被子进程继承可以使用env查看bash进原创 2020-11-25 19:36:12 · 125 阅读 · 0 评论 -
UNIXC01 多模块开发, GDB调试器
多模块开发介绍为什么将项目分为多个模块?将大型项目分割为多个模块, 便于团队的协作开发, 而不是将所有的函数放在一个源文件中.便于错误的查找和调试, 每个模块可以单独的编译(gcc -c *.c)将编译好的没有语法错误的模块链接(gcc *.o)为一个可执行程序(a.out)实施步骤定义各个模块间的接口模块间的接口定义, 在C语言中使用头文件实现分模块实施每个模块都遵守定义好的头文件, 实现各自的接口独立编译(gcc -c *.c)各个模块, 检查模块的语法错误将原创 2020-11-25 12:31:47 · 108 阅读 · 0 评论 -
UNIXC01 程序构建过程
从源码到到可执行程序程序的构建过程预处理: 源文件(hello.c, stdio.h,…) 经过预处理器(cpp) 预处理得到 hello.i ,这个过程做了预处理指令执行, 和注释消除gcc -E hello.c -o hello.i编译: gcc将C语言编译为汇编语言文件 hello.s ,这个过程中会检查语法错误, 但不会检查逻辑错误gcc -S hello.i -o hello.s汇编: 再将汇编语言文件hello.s做汇编形成机器指令文件(目标文件) hello.o.原创 2020-11-23 20:50:55 · 127 阅读 · 0 评论