Linux学习笔记
1.信号(文件名k0224)
1.通知进程产生了某种事件,进程可能产生某些错误。
2.Kill发送信号9
3.Signal可以改变信号的响应方式。1.默认,2.忽略3.自定义
4.看信号的地方:Usr/include/bits/signum.h
5.9号信号不可以改变,只可以按默认的执行。15号可以终止进程,killed是9号信号,Terminated是15号信号。
6.实现signal 32位 long signal长整型 发几号就把进程的pcb第几位置为1,然后查表去执行相关函数。
7.Fork+exec实现命令解释器(bash.c)
1①输出提示符
②从键盘获取将要执行的命令名字
③解析命令及参数,处理异常
④分类实现,一是内置命令(方向键如cd,exit,用which找不到的都是)二是普通命令,用fork和exec实现(注意僵死进程)
⑤循环不断执行输入的命令 自己实现命令(ps,kill,ls,vi,mkdir,pwd,cp)
程序设计第五章,ls104页
8.自己实现的kill(mykill.c)
#include<stdio.h>
2 #include<stdlib.h>
3 #include<unistd.h>
4 #include<string.h>
5 #include<signal.h>
6 void fun2(int sig)
7 {
8 exit(sig);
9 }
10 void fun(int sig)
11 {
12
13 printf("sig=%d\n",sig);
14 //signal(sig,SIG_DFL);//默认
15 //signal(sig,fun2);
16 // signal(sig,SIG_IGN);//忽略
17 //
18 }
19 int main()
20 {
21 signal(SIGINT,fun);//内核帮用户调用的
22 while(1)
23 {
24 printf("hello\n");
25 sleep(1);
26 //signal(SIGINT,);
27 }
28 printf("main over\n");
29 exit(0);
30
31 }
~
****进程间通信:管道,信号量,共享内存,消息队列,套接字
管道有同步,在内存中使用方便。
有名管道,mkfifo fifo创建管道
无名管道。(在父子进程间使用)
面试:1.管道是半双工,对讲机(半双工,同一时刻只能发或收)
单工(只能接受或发送)
全双工(吵架)
2.区别:任意两个进程
无名:只在父子进程间通讯。
3.管道在内存上存着。写入管道的文件在内存中
写端彻底关闭,读端read返回值为0;
读关闭,写端会引发异常,SIGPIPE信号。
信号量:pv操作,临界区,临界资源。
信号量(特殊的变量):(2019.3.9)k0309—a.c b.c sem.c
Ulimit -a(查看限制信息)
Ulimit -代号 可以改大小(不能永久改变,只能临时改变。)
信号量:特殊的变量,值可以改变,对信号量加一减一的操作都是原子操作,p操作对信号量的值进行原子减一,
p代表申请资源。
信号量值为0的时候则p操作阻塞,
v操作是对信号量的原子加一,不会阻塞。V代表释放资源,
作用:同步进程
临界资源:同一时刻只允许一个进程(线程)访问的资源
临界区:访问临界资源的代码段。
二值信号量:0,1
计数信号量:有个数值计数用值大于一的信号量
接口:
创建并初始化
Pv操作,销毁信号量
ipcs可以看进程间的通信-s看信号量-q消息队列-m共享内存
ipcsrm - s +id删除信号量
getconf LONG_BIT看Linux是多少位的(32位)
IPC(进程间通信)
2.共享内存
(1.申请一块空间作为共享内存,
2.将将共享内存映射到多个进程的地址中
接口:shmget()//创建
Shmat()//映射到进程地址空间
Shmdt()//断开映射
Shmctl()//删除共享内存
1.确定信号量数量,由控制点决定
2.赋初值
3.Pv操作同步
4.扩展:广义共享内存实现几种方式《内核代码分析》
3.消息队列
放入消息:(a.c)
1#include<stdio.h>
2 #include<stdlib.h>
3 #include<assert.h>
4 #include<string.h>
5 #include<unistd.h>
6 #include<sys/msg.h>
7 struct mess
8 {
9 long type;
10 char buff[32];
11 };
12 int main()
13 {
14
15 int msgid=msgget((key_t)1234,IPC_CREAT|0600);
16 assert(msgid!=-1);
17
18 struct mess dt;
19 dt.type=1;
20 strcpy(dt.buff,"hello1");
21
22 msgsnd(msgid,(void *)&dt,32,0);
23 }
~
获取消息:(b.c)
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<assert.h>
4 #include<string.h>
5 #include<unistd.h>
6 #include<sys/msg.h>
7 struct mess
8 {
9 long type;
10 char buff[32];
11 };
12 int main()
13 {
14
15 int msgid=msgget((key_t)1234,IPC_CREAT|0600);
16 assert(msgid!=-1);
17
18 struct mess dt;
19
20 msgrcv(msgid,(void *)&dt,32,1,0);//把1变为0后代表不区分消息类型,从上往下依次获取。
21 printf("dt.buff==%s\n",dt.buff);
22
23 exit(0);
24 }
~
线程(进程内部的一条执行路径或序列)(调度执行角度)进程:一个正在运行的程序(分配资源角度)
并发,同步,
线程函数
操作系统描述的实现:
编译时要加线程的库
(gcc -o main main.c -lpthread) k0317 main.c
1#include<stdio.h>
2 #include<stdlib.h>
3 #include<assert.h>
4 #include<string.h>
5 #include<unistd.h>
6 #include<sys/msg.h>
7 void * thread_fun(void *arg)
8 {
9
10 int i=0;
11 for(;i<7;++i)
12 {
13 printf("fun run\n");
14 sleep(1);
15 }
16 pthread_exit("fun over");
17 }
18 int main()
19 {
20 pthread_t id;
21
22 pthread_create(&id,NULL,thread_fun,NULL);
23
24 int i=0;
25 for(;i<3;++i)
26 {
27 printf("main run\n");
28 sleep(1);
29 }
30 char *s=NULL;
31 pthread_join(id,(void**)&s);//等待子线程完成
32 printf("s==%s\n",s);
33 exit(0);//退出进程,线程中不调用
34 //pthread_exit(NULL)// 退出线程
35 }
五个线程并发执行k0317 main1.c
#include<stdio.h>
2 #include<stdlib.h>
3 #include<assert.h>
4 #include<string.h>
5 #include<unistd.h>
6 #include<sys/msg.h>
7 #include<pthread.h>
8
9 #define MAXID 5
10
11 void *thread_fun(void *arg)
12 {
13 int index=(int )arg;//转为int
14 int i=0;
15 for(;i<4;i++)
16 {
17 printf("index=%d\n",index);
18 sleep(1);
19 }
20 }
21
22 int main()
23 {
24 pthread_t id[MAXID];
25
26 int i=0;
27 for(;i<MAXID;i++)
28 {
29 pthread_create(&id[i],NULL,thread_fun,(void*)i);//void*类型指定大小,要四个字节
30 }
31
32 for(i=0;i<MAXID;i++)
33 {
34 pthread_join(id[i],NULL);
35 }
36 exit(0);
37 }
处理器数目有关问题:k0317 main2.c
1#include<stdio.h>
2 #include<stdlib.h>
3 #include<assert.h>
4 #include<string.h>
5 #include<unistd.h>
6 #include<sys/msg.h>
7 #include<pthread.h>
8
9 #define MAXID 5
10 int g=1;
11
12 void *thread_fun(void *arg)
13 {
14 int i=0;
15 {
16 for(;i<1000;i++)//最后g小于等于5000,
17 {
18 printf("d=%d\n",g++);
19 }
20 }
21 }
22
23 int main()
24 {
25 pthread_t id[MAXID];
26
27 int i=0;
28 for(;i<MAXID;i++)
29{
30 //pthread_create(&id[i],NULL,thread_fun,(void*)i);//void*类型指定大小,要四个字节
31 pthread_create(&id[i],NULL,thread_fun,NULL);//void*类型指定大小,要四个字节
32 }
33
34 for(i=0;i<MAXID;i++)
35 {
36 pthread_join(id[i],NULL);
37 }
38 exit(0);
39 }
同步线程:
四种方法:信号量,互斥锁,条件变量,读写锁
信号量;pv操作
sem_wait(&sem);//p操作
printf(“d=%d\n”,g++);
sem_post(&sem);//v操作
1#include<stdio.h> k0321 main.c
2 #include<stdlib.h>
3 #include<assert.h>
4 #include<string.h>
5 #include<unistd.h>
6 #include<sys/msg.h>
7 #include<pthread.h>
8 #include<semaphore.h>
9
10 #define MAXID 5
11
12 sem_t sem;//
13 int g=1;
14
15 void *thread_fun(void *arg)
16 {
17 int i=0;
18 {
19 for(;i<1000;i++)//最后g小于等于5000,
20 {
21 sem_wait(&sem);
22 printf("d=%d\n",g++);
23 sem_post(&sem);
24 }
25 }
26 }
27
28 int main()
29 {
30 pthread_t id[MAXID];
31 sem_init(&sem,0,1);//初始化信号量值为1;
32 int i=0;
33 for(;i<MAXID;i++)
34 {
35 //pthread_create(&id[i],NULL,thread_fun,(void*)i);//void*类型指定大小,要四个字节
36 pthread_create(&id[i],NULL,thread_fun,NULL);//void*类型指定大小,要四个字节
37 }
38
39 for(i=0;i<MAXID;i++)
40 {
41 pthread_join(id[i],NULL);
42 }
43 sem_destroy(&sem);
44 exit(0);
45 }
看线程id ,个数 ps-eLf
条件变量:
K0321 cond.c
Top(显示一些信息关于cpu的)?
设置cpu的性能,taskset,指定某个进程在某个核心上执行。
Cpu亲和性
使用多处理器资源,同时做两件以上事情,时候用线程
线程怎么实现(内核设计4.3,3线程实现)在Linux中实际是进程实现,调用clone()
Strace ./a 跟踪系统调用
Ltrace跟踪库函数的调用
网络编程
Thread线程
同步

线程间通信问题(同步)四种方法:
用户可以用:
信号量;
互斥锁
条件变量
读写锁
内核空间的方法:自旋锁
4.进程
Ulimit -s看栈的大小
问题:
一个进程可以创建多少个线程 大约300左右,栈大小有影响,默认情况下用户只能创建1024个进程,main.c
线程安全函数(可重入函数:)
Strtok不可以在多线程中使用,要使用sttok_r a.c
加了_r的是可重入函数,例如localtime
多线程中执行fork会怎么样
Gdb调试方法
l显示代码 l add.c:2跳转到add.c的第二行
b加断点
n单步执行
p打印某个变量的值
infobreak查看断点
delete+断点编号删除断点
c继续执行
s进入函数
finish退出函数
bt查看函数调用关系
display
线程调试:
Info threads显示调试的线程
thread +id 切换到指定线程
set schedule-locking off/on/step
多进程:
set follow-fork-mode child 设置跟踪子进程
attach +pid 选择某个进程调试
7,4模型
tcpudp协议
端口
Ip
粘包:就是发了好多次数据一次接收到了,分不清了,解决办法是控制发送,明确起始,终止。
5.套接字
netstat -n -a监听套接字,t显示tcp,p显示pid(看接收,发送缓冲区的字符数)
发送缓冲区,接收缓冲区附着在连接上
多线程解决多客户端访问服务器,(2、3十个可以)io函数可以解决
三次握手四次挥手
为什么是三次握手;如果是两次的话,服务器关闭了,客户端就会一直等待着,占用的文件描述符,
怎么区分断电还是长久不发数据,
断网了不会发数据,发心跳包(隔一段时间会发送一个恒定的包,三个包没发就会认为断开了)
拔掉网线,连接会断开。
Sendto发多大就会分开发?
6.io复用函数
K0414,io复用函数 select,poll,epoll;
高性能服务器编程第九章
2019.4.18
Io复用Select()
Poll()
Epoll()
创建内核事件=-----红黑树
添加:每个描述符只添加一次
直接获得就绪的描述符O(n)
内核实现:注册回调函数,通过回调函数添加到就绪队列
7.*ET LT模式区别
***ET LT模式区别
ET 只能使用非阻塞模式(减少返回次数,只返回一次),fcntl开启高效模式:发一次数据才会提醒一次,只提醒一次,无论处理还是未处理完,只提醒一次。客户端一关,服务器就崩掉了,原因是:
LT(没读完io提醒继续读,直到读完为止)默认反复提醒,返回次数为字符数
守护进程(编程流程):
1.fork()退出父进程
2.setsid()创建新会话
3.fork()退出父进程(失去会话组长,进程组长的身份)
4.改变工作路径:chdir(“/”)改到根目录(不可被卸载的目录)
5.Umask掩码全部清零设置为000 (umask 0),掩码(002)中有什么权限,创建的文件就缺什么
6.关闭所有描述符close()
7.//(关闭僵死进程)
Chkconfig查看后台的服务
8.UNIX第十三章
Libevent库UNIX第十二章
安装tar.gz包的一般过程
1.tar zxf libevent-2.0.19-stable.tar.gz(包名)
2.cd libevent-2.0.19-stable (进入目录)
3…/configure prefix=/usr 如果不够,从此处开始管理员操作。
4.Make 一般用户
5.Make install(root) 要切换到管理员
6.验证 ls /usr/lib |grep event,如果有好多就是对的
如果失败,重新安装,无须删除原文件,会覆盖掉。
Ldd查看程序的共享库
Libevent 的使用
9.shell编程
脚本:解释型语言(要解释器),pathon,
、c编译型
Java两个都要
1.变量:本地变量(赋值时等号左右两边不能有空格),环境,参数
2.条件判断
3.循环
4.函数
一级提示符
Echo$PS1
可以修改一级提示符,PS1,[ ]左右两边有空格
Pycharm
Touch 文件名创建文件
2019.5.5
运行脚本 ./名字(加执行权限,chmod u+x 名字)
Bash ./m名字 (不加权限)
脚本调用另外一个脚本,实际用了另外一个解释器
. ./a.sh 会在本bash中执行脚本,
.可以替换为source
C语言调用脚本程序
1.Fork()
2.Execl(”./a.sh”,脚本参数)
Mail查看收到的邮件 邮件存放在var下面
发送邮件
echo “hello 这是晚上?” |mail -s “有空吗” yhx //-后是标题,后面是接受者的用户名
AWK的使用
awk -F. ‘{print $1}’ file > newfile //可以把浮点数的整数部分提取到newfile中’’
awk -F : ‘{print $1"\t"$3}’ a //提取a中的用户名和pid\t可以格式化输出
awk -F : ‘{print $1,$3}’ a
awk -F : ‘{if($3>=500)print $1"\t"$3}’ a //输出第三个参数>=500的
SED使用(文件编辑,)
增加一行,删除一行,在哪插入。
Sed ‘’输入文件输出文件
sed ‘2i\hello’ file >newfile //插入,在第二行之前
sed ‘2a\hello’ file >newfile //附加,在第二行后插入
sed -n ‘2,3p’ file >newfile //只输出2,3行
sed ‘2,3p’ file >newfile //附加二三行后输出
sed ‘3d’ file >newfile //删除第三行
2174

被折叠的 条评论
为什么被折叠?



