Linux系统编程
Linux系统编程
剑决浮云气
事了拂衣去,深藏功与名
展开
-
浅谈linux的命令行解析参数之getopt_long函数
转载地址转载 2021-09-06 15:19:08 · 94 阅读 · 0 评论 -
动态报式套接字
1.存在的问题上一次我们在协议中定义了这样一个内容#ifndef __PROTO_H__#define __PROTO_H__#define NAMESIZE 11#include <stdint.h>#define RCVPORT 1989struct msg_st{ uint8_t name[NAMESIZE]; uint32_t math; uint32_t eng;}__attribute((packed));原创 2021-08-26 11:13:55 · 123 阅读 · 0 评论 -
初探socket 报式
1.socket一般来说socket有一个别名也叫做套接字。socket起源于Unix,都可以用“打开open –> 读写write/read –> 关闭close”模式来操作。Socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭)。说白了Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面原创 2021-08-25 20:39:05 · 821 阅读 · 0 评论 -
初探共享内存
1.什么是共享内存?共享内存就是允许两个或多个进程共享一定的存储区。就如同 malloc() 函数向不同进程返回了指向同一个物理内存区域的指针。当一个进程改变了这块地址中的内容的时候,其它进程都会察觉到这个更改。因为数据不需要在客户机和服务器端之间复制,数据直接写到内存,不用若干次数据拷贝,所以这是最快的一种IPC。注:共享内存没有任何的同步与互斥机制,所以要使用信号量来实现对共享内存的存取的同步。2.共享内存特点和优势当中共享内存的大致原理相信我们可以看明白了,就是让两个进程地址通过页表映射到同一原创 2021-08-25 11:38:26 · 116 阅读 · 0 评论 -
初探信号量
1.信号量信号量本质上是一个计数器(不设置全局变量是因为进程间是相互独立的,而这不一定能看到,看到也不能保证++引用计数为原子操作),用于多进程对共享数据对象的读取,它和管道有所不同,它不以传送数据为主要目的,它主要是用来保护共享资源(信号量也属于临界资源),使得资源在一个时刻只有一个进程独享。2.信号量的工作原理由于信号量只能进行两种操作等待和发送信号,即P(sv)和V(sv),他们的行为是这样的:(1)P(sv):如果sv的值大于零,就给它减1;如果它的值为零,就挂起该进程的执行(2)V(sv原创 2021-08-25 11:08:43 · 385 阅读 · 0 评论 -
初探消息队列
1.消息队列消息队列本质上是位于内核空间的链表,链表的每个节点都是一条消息。每一条消息都有自己的消息类型,消息类型用整数来表示,而且必须大于 0。每种类型的消息都被对应的链表所维护消息队列是全双工的2.消息队列相关的函数// 创建和获取 ipc 内核对象int msgget(key_t key, int flags);// 将消息发送到消息队列int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);// 从消息队列获原创 2021-08-24 17:33:17 · 149 阅读 · 0 评论 -
初探管道..
进程间通信 IPC1.管道匿名管道pipe();命名管道内核提供管道和队列没什么区别管道有自同步机制(迁就慢的那一方)单工2.pipe匿名管道可以用在具有亲缘关系的进程之间NAME pipe, pipe2 - create pipeSYNOPSIS #include <unistd.h> int pipe(int pipefd[2]);创造一个管道,返回给你两个文件描述符 0是读 1是写先pipe,然后在fork,子进程原创 2021-08-23 22:43:38 · 96 阅读 · 0 评论 -
Linux文件描述符到底是什么?
点击此处转载 2021-08-23 17:39:56 · 115 阅读 · 0 评论 -
文件锁的函数
1.flockNAME flock - apply or remove an advisory lock on an open fileSYNOPSIS #include <sys/file.h> int flock(int fd, int operation);测试demo#define PROCNUM 20#define FILENAME "log"#define LINESIZE 1024void addFun(void原创 2021-08-23 13:20:50 · 112 阅读 · 0 评论 -
高级IO的其他函数
1.readv和writev NAME readv, writev, preadv, pwritev - read or write data into multiple buffers SYNOPSIS #include <sys/uio.h> ssize_t readv(int fd, const struct iovec *iov, int iovcnt); ssize_t writev(int fd, const struct iovec *iov, int原创 2021-08-23 11:19:52 · 96 阅读 · 0 评论 -
I/O多路转接
1.作用①监视文件描述符的行为②I/O多路转接技术:先构造一张有关描述符的列表,然后调用一个函数,知道这些描述符中的一个已准备好进行I/O时,给函数才返回。在返回时,它告诉进程哪些描述符已准备好可以进行I/O。2.select函数以事件为单位 监视文件描述符。 监视事件单一int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);原创 2021-08-22 11:05:59 · 96 阅读 · 0 评论 -
有限状态机编程
1.概念有限状态机,(英语:Finite-state machine, FSM),又称有限状态自动机,简称状态机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型。2.数据中继终端1向终端2发送数据,然后终端2进行处理后,在发送回终端1也就是一个myCpy的重构3.代码#define TTY1 "/dev/tty11"#define TTY2 "/dev/tty12"#define BUFSIZE 20enum{ STATE_R = 1, STATE_W, STATE_E原创 2021-08-18 21:31:24 · 474 阅读 · 1 评论 -
线程与信号
1.属性①每个线程都有自己的信号屏蔽字②但是信号的处理是进程中所有进程共享的③进程中的信号是递送到单个线程的,只体现在该进程的pedding上,(谁来响应 就要看从kernel态到usr态 调度的是哪个线程)。首先先拿线程的mask和进程的pedding按位与,在那线程mask和线程pedding按位与④一个线程给一个线程发信号,体现在该线程的pedding上2.函数pthread_sigmaskNAMEpthread_sigmask - examine and change mask of原创 2021-08-18 16:35:21 · 331 阅读 · 0 评论 -
互斥量+条件变量实现 信号量
1.互斥量和信号量我们可以简单地把这个互斥量理解成一个bool类型可以把信号量理解成一个int类型2.以前写过一个程序,用201个线程实现多线程求一段区间内的质数现在给定一定数目的线程资源,来求取一段区间内的质数条件变量 + 互斥量 实现信号量信号量只要满足需求 就可以使用参考哲学家就餐问题#ifndef __MYSEM_H__#define __MYSEM_H__typedef void mysem_t ;mysem_t * mysem_init(int value);int原创 2021-08-16 15:41:49 · 260 阅读 · 0 评论 -
条件变量对多线程求素数的改进
代码#define LEFT 30000000#define RIGHT 30000200#define SIZE 4pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;pthread_cond_t cond = PTHREAD_COND_INITIALIZER;//0代表池中没有任务 >0 代表有任务 -1代表全部计算完成int nPool = 0;void * Fun(void *p){ int nNum; int原创 2021-08-15 20:40:52 · 125 阅读 · 0 评论 -
线程令牌桶的实现及条件变量改进版本
【互斥锁版本】注意,若不满足到对某资源进行操作的条件,则一直while循环,反复轮询“开锁——等待——加锁”的过程,会造成“忙等”的现象。解决方法是通过条件变量的方式。会很占CPU的资源struct mytbf_st{ int token;//积累的传输量 int burst;//传输量的最大限制 int cps;//每秒增加的传输量 int pos;//在数组中下标的位置 pthread_mutex_t mut;//我们需要对token进行操作 需要加锁}原创 2021-08-15 16:50:52 · 174 阅读 · 0 评论 -
一个简单进程池的实现
1.要求计算一段区间内的质数main线程创建了4个兄弟线程,他们用一个全局变量nPool来进行通信nPool = 0 代表计算完成需要main发布任务nPool > 0 代表main线程任务已经发布,四个兄弟线程可以去抢任务了nPool = -1 代表所有任务已经发布完毕了2.代码#define LEFT 30000000#define RIGHT 30000200#define SIZE 4pthread_mutex_t mutex = PTHREAD_MUTEX_INITIA原创 2021-08-13 21:12:26 · 275 阅读 · 1 评论 -
初探互斥量
1.互斥量的概念前面已经提及2.一个demo要求 四个线程,每个线程分别输出a b c d,是拼命输出,如何让他们在终端上输出顺序的a b c dpthread_mutex_t mut[THRNUM];void * Fun(void *p){ int c = 'a' + (int)p; int i = (int)p; int next = (i+1)%THRNUM; while(1) {原创 2021-08-12 20:43:21 · 96 阅读 · 0 评论 -
初探线程之线程竞争及故障
1.一个demo#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <pthread.h>#define LEFT 30000000#define RIGHT 30000200#define SIZE (RIGHT-LEFT+1)void * Fun(void *p){ int nNum = * (int *)p; int Flag = 1;原创 2021-08-12 20:36:56 · 158 阅读 · 0 评论 -
初探线程02
1.线程的取消NAME pthread_cancel - send a cancellation request to a threadSYNOPSIS #include <pthread.h> int pthread_cancel(pthread_t thread);①取消有两种状态,允许和不允许②允许取消又分为异步cancel推迟cancel(默认) 推迟到cancel点才被响应cancel点: posix定义的cancel点 都是可能引发阻塞的系原创 2021-08-12 16:30:49 · 84 阅读 · 0 评论 -
初探线程01
1.线程的概念①线程就是一个正在运行的程序②是main线程在运行,不是主线程,没有主次之分,线程之间是平等的关系③多个线程共享内存,在同一块内存空间内④他们之间的通讯会很简单,他们打开的文件描述符都一模一样的,或者一个全局变量等等⑤从并发角度来看, 线程比进程简单,线程是先标准化,才被实现出来⑥POSIX线程是一个标准 pthread_t 类型⑦CPU的调度是以线程为单位的⑧Compile and link with -pthread2.你的会话是一个容器,用来容纳进程组,你的进程组是一原创 2021-08-11 20:35:08 · 126 阅读 · 0 评论 -
实时信号.
1.区别与时间的关系:实时和非实时信号非实时信号都不支持排队,都是不可靠信号;实时信号都支持排队,都是可靠信号非实时信号 是用位图的形式来做的,所以会产生信号丢失1 信号本质软中断信号(signal,又简称为信号)用来通知进程发生了异步事件。在软件层次上是对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的。信号是进程间通信机制中唯一的异步通信机制,一个进程不必通过任何操作来等待信号的到达,事实上,进程也不知道信号到底什么时候到达。进程之间可以互相通过系统调用转载 2021-08-10 19:24:27 · 310 阅读 · 0 评论 -
sigsuspend/sigaction
1.一段代码存在的问题因为操作是不原子的void Handler(int n){ write(1, "!", 1);}int main(){ int i; sigset_t set; sigemptyset(&set); sigaddset(&set, SIGINT); signal(SIGINT, Handler); while(1) {原创 2021-08-10 17:45:25 · 169 阅读 · 0 评论 -
信号集 信号屏蔽字/pending的处理
1.相关函数NAME sigemptyset, sigfillset, sigaddset, sigdelset, sigismember - POSIX signal set opera‐tions.SYNOPSIS #include <signal.h> int sigemptyset(sigset_t *set); int sigfillset(sigset_t *set); int sig原创 2021-08-09 16:16:16 · 139 阅读 · 0 评论 -
setitime和相关函数
1.setitime误差很小NAMEgetitimer, setitimer - get or set value of an interval timerSYNOPSIS#include <sys/time.h>int getitimer(int which, struct itimerval *curr_value);int setitimer(int which, const struct itimerval *new_value, struc原创 2021-08-08 19:57:55 · 120 阅读 · 0 评论 -
多任务计时器anytime
#ifndef __MY_ALARM_H#define __MY_ALARM_H //最多创建1024个任务#define MAX 1024//函数定义typedef void alarm_func_t(void*);//添加任务,成功返回任务ID,失败返回-1int anytimer_alarm(int sec, alarm_func_t *func, void *ch);//取消任务 成功返回0,失败返回-1;int anytimer_destory(int id);#en原创 2021-08-08 19:22:20 · 761 阅读 · 0 评论 -
令牌桶封装成库
1.一个令牌桶的三要素①token 当前的令牌个数②cps当前的流速③burst最大令牌数简单实现mytbf.h#ifndef __MYTBF_H__#define __MYTBF_H__//数组的大小 也就是说总共有1024个桶#define MYTBF_MAX 1024//对内部的数据结构进行一个封装返回void * typedef void mytbf_st;//这里返回一个void*mytbf_st * InitMytbf(int nCps, int nBurst);原创 2021-08-07 19:41:56 · 126 阅读 · 0 评论 -
漏桶算法和令牌桶算法
1.漏桶算法漏桶算法思路很简单,水(请求)先进入到漏桶里,漏桶以一定的速度出水,当水流入速度过大会直接溢出,可以看出漏桶算法能强行限制数据的传输速率。图1 漏桶算法示意图在某些情况下,漏桶算法不能够有效地使用网络资源。因为漏桶的漏出速率是固定的参数,所以即使网络中不存在资源冲突(没有发生拥塞),漏桶算法也不能使某一个单独的流突发到端口速率。因此,漏桶算法对于存在突发特性的流量来说缺乏效率。而令牌桶算法则能够满足这些具有突发特性的流量。通常,漏桶算法与令牌桶算法可以结合起来为网络流量提供更大的控制。原创 2021-08-07 15:20:53 · 262 阅读 · 0 评论 -
linux信号常用函数
1.kill发送一个信号给一个进程NAME kill - send signal to a processSYNOPSIS #include <sys/types.h> #include <signal.h> int kill(pid_t pid, int sig);DESCRIPTION The kill() system call can be used to send any signal to any process group o原创 2021-08-06 20:54:10 · 201 阅读 · 0 评论 -
linux中的信号
1.概念信号是软件中断。信号的响应依赖于中断2.kill -l1-31是标准信号34-64是 实时信号原创 2021-08-06 15:57:33 · 109 阅读 · 0 评论 -
初探系统日志
一个简单的demo#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <syslog.h>#include <error.h>#define FNAME "/tmp/out"int DaemonFun(){ pid_t pi原创 2021-08-05 17:13:48 · 60 阅读 · 0 评论 -
初探守护进程
1.概念守护进程(Daemon)是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。通常是一个会话的leader,一个进程组的leader守护进程一般不需要收尸,一般父进程fork后,直接退出2.前台进程组 后台进程组详细进程组是一组相关关进程的集合,会话是一組相关进程组的集合①有控制终端的属于前台,没有控制终端的或者是隐藏了的叫后台进程3.会话由于Linux是多用户多任务的分时系统,所以必须要支持多个用户同时使用一个操作系统。当一个用户登录一次系原创 2021-08-05 16:16:41 · 71 阅读 · 0 评论 -
更改用户ID和组ID
1.问题的引入普通用户是无法查看/etc/shadow文件的,但是当普通用户使用命令passwd去修改自己的口令的时候,确实可以成功的。修改口令一定会改变/etc/shadow文件,那么是如何做到的呢?2.查看passwd注意在用户属性上面有一个S , 那就是set uid是为了让一般用户在执行某些程序的时候,能够暂时具有该程序拥有者的权限SUID仅 可用在“二进制文件(binary file)”,SUID因为是程序在执行过程中拥有文件拥有者的权限,因此,它仅可用于二进制文件,不能用在批处理文件原创 2021-08-02 16:00:01 · 1240 阅读 · 0 评论 -
进程-命令的实现
1.例如ls我们在当前的shell终端上,运行我们所写的程序,shell会先进行fork,创造出一个和shell一模一样的进程,然后立即执行exec操作,摇身一变,运行。此时shell就在等待该进程结束,wait。在prime1中,我们没有添加wait操作,所以当父进程创建完进程之后,就返回了,父进程创造的所有的子进程都变成了孤儿进程,被init接管,所以会先显示出终端的内容为什么被init进程接管后,还会在终端上输出呢?因为父进程的文件描述符中,至少会默认打开三个 0 1 2 stdin st原创 2021-08-01 08:41:31 · 85 阅读 · 0 评论 -
exec函数族
1.一个问题当fork的时候,前面提到过fork是复制进程当前的运行环境,创造出一个和他一模一样的进程,那么当我们在终端上创建一个进程的时候为什么创建的不是一个终端呢?2.exec函数族 PID不会变①fork函数创建子进程后,子进程一般要调用exec函数以执行另外一个程序。当进程调用一个exec函数的时候,子进程执行的程序会被替换为新程序,新程序从main函数开始执行,而且exec不创建新的进程,所以不会改变进程号。exec只是用磁盘上的新程序来代替当前进程的正文段,数据段,堆,栈NAME原创 2021-07-27 19:14:31 · 89 阅读 · 0 评论 -
进程分配之交叉分配法
1.思路创建三个进程,给定一段区间,把任务轮流分配给三个进程,任务0给进程0,任务1给进程1,任务2给进程2,任务3给进程0…2.进程的交叉分配法 实现 查找质数#include <stdio.h>#include <stdlib.h>#include <unistd.h>#define LEFT 30000000#define RIGHT 30000200#define N 3int main(){pid_t pid;int i,j,Fl原创 2021-07-27 16:56:56 · 751 阅读 · 0 评论 -
wait和waitpid
1.waitNAME wait, waitpid, waitid - wait for process to change stateSYNOPSIS #include <sys/types.h> #include <sys/wait.h> pid_t wait(int *status);父进程一旦调用了wait就立即阻塞自己,由wait自动分析是否当前进程的某个子进程已经退出,如果让它找到了这样一个已经变成僵尸的子进程,wait就会收集这原创 2021-07-27 12:16:41 · 55 阅读 · 0 评论 -
fork的写时复制1
一段测试代码#include <stdio.h>#include <stdlib.h>#include <unistd.h>int main(){ pid_t pid; int nNum = 0; printf("Pid : [%d] \n", getpid()); pid = fork(); if(0 == pid) { nN原创 2021-07-26 19:52:22 · 88 阅读 · 0 评论 -
frok的一个Demo测试素数
1.代码#include <stdio.h>#include <stdlib.h>#include <unistd.h>#define LEFT 30000000#define RIGHT 30000200int main(){ pid_t pid; int i,j,Flag; //Flag是判断是否是素数的标志 for(i = LEFT ; i <= RIGHT; i++) { pid = fo原创 2021-07-26 19:44:01 · 55 阅读 · 0 评论 -
进程标识符及fork
1.进程标识符①pid,通常是一个有符号的,16位的一个整形数我在centos下测试了 是占四个字节②类型pid_t③文件描述符优先使用最小的,但是进程描述符是一次使用最小的,就算前面有释放的,也不会使用④两个函数getpid和getppid#include <sys/types.h>#include <unistd.h>#include <stdio.h>int main(){ printf("MyPid = %d\n", getp原创 2021-07-26 18:51:20 · 347 阅读 · 0 评论