初识Linux编程

初识Linux编程

最近操作系统作业有不少linux编程的内容,啥子waitsignalexitexec,等等函数简直打脑壳,从来就没接触过,实在是看不懂,经过我一番研究还是有所收获


僵尸进程、孤儿进程

一说到僵尸进程,我之前听到军儿哥说过,但是还是没搞清楚,从名字上看始终就感觉想啥子病毒程序那种。
这篇博客很好。。僵尸进程与孤儿进程
总而言之喃就是,孤儿进程就是他的父进程已经死了,子进程就成了孤儿,然后被一个init进程收养,并且这个init进程会自动处理所有的孤儿进程。而僵尸进程就是子进程死了,但是他的父进程有没有来给他收尸,所以常年就飘泊在外面就像僵尸一样,但是这个僵尸很乖,不会像行尸走肉中的僵尸那么吃得,也不会像九叔对付的僵尸那么强,这儿的僵尸只是啥子都不敢但是占用了pid,他占用其实没啥子,关键就是这个pid是有限的,一占用多了就要出问题。
根据上面那片博客中的例子,再查看所有僵尸进程的时候可以通过top,也可以通过ps命令,但是ps命令不是自动的动态更新的,所以就写个小脚本动态查看

#!/bin/bash
while true
	do
		clear
		echo 's  pid   ppid   commond'
		echo '-------------'
		ps -A -o s,pid,ppid,cmd| grep -e '^[Zz]'
		sleep 1
	done

这里里面-A是查看所有的结果,-o是自定义格式,s是进程的状态,进程的状态有R运行态,S睡眠,Z僵尸进程等。。ppid父进程的pid, 然后把结果再用grep的正则表达式来筛选输出
而测试代码就是上面博客中的代码这就不粘了~在这里插入图片描述

还有就是通过top的交互式命令的方式查看生成僵尸进程

在这里插入图片描述

僵尸进程的预防办法就是上面那片博客中所说的通过wait函数, 或者waitpid函数,子进程在终结的时候都回向父进程发送SIGCHLD信号,父进程也可通过signal函数去处理
wait函数详细分析

然后我发现一个小东西就是进程在sleep的时候是会别捕捉到的信号唤醒的,不管是SIGINT这个终止进程信号,还是只是普通的闹钟信号SIGALRM,都会影响到正在执行的那个sleep,比如我的这一段代码在这里插入图片描述
打印TTTT之前应该是要睡100秒的(linux中好像是以秒为单位,不是以毫秒为单位),但是正因为我前面一句有个一秒钟的闹钟,所以100秒的睡眠会被唤醒
这篇博客还可以sleep与信号唤醒
然后很快就打印了很多TTTT了
在这里插入图片描述

Linux系统信号

上面waitsignal都可以接受和发送很多信号,但是这信号到都有些什么用,什么时候用?说实话我还没有自己仔细研究,先记下来,等比赛完考了研再来慢慢研究
linux内核信号是如何处理的
linux信号的默认处理

linux多线程

这篇对linux线程的讲解很详细在linux中使用多线程
我刚开始的时候,以为是pthread_join函数才是开启线程的意思, 后头经过实验发现其实pthread_create的时候已经就创建线程并开启线程了。
这里有个小东西就是传参的问题

#include<pthread.h>
#include<stdio.h>
#include<unistd.h>

void test(int *input){
	int i;
	for(i = 0; i < 5; i ++){
		printf("-------%d\n", *input);
		sleep(1);
	}
}

int main(){
	pthread_t thread;
	int input = 1;
	pthread_create(&thread, NULL, (void *)test, &input);
	sleep(3);	
	input = 2;
	while(1);
	return 0;
}

我在最后加了一个死循环因为如果没有这个死循环,又没有pthread_join的情况,这个进程就不回去等自己的线程执行完就死了,所以必须要加一个东西
这段代码的结果是
在这里插入图片描述
为什么只出现了3个1,然后后面全是2喃?因为穿的参数是指针,而后面又改了这个指针中的内容。

exec函数族

exec函数族解析
exec函数族就是在一个进程中,去调用另一个进程,不管可以调用自己写的exe,还可以调用shell

lockf函数

这里再额外提一下lockf函数,就是控制不同进程输出的时候,不要串在一起了。。我这里只讨论lockf中第一个参数为1(也就是打印到控制台的情况)
这里有几点要注意的

  1. lockf函数并不会控制线程间的互斥输出,只控制进程间的互斥输出,下面是代码和结 果,毕竟这些线程都是处于同一个进程的,而lockf只是进程互斥在这里插入图片描述在这里插入图片描述
  2. 在实验lockf的时候可能会被printf或者putchar的缓冲区机制影响是实验结果
    在多进程的情况下,很容易会出现打印的时候内容串在一起的情况,我这里为了让结果更明显,我就在循环中加了sleep函数在这里插入图片描述

这段代码的结果为:在这里插入图片描述

而如果加了锁的情况就不同了,这位了不让父进程先退出,子进程变成孤儿乱打印就加了个wait
在这里插入图片描述

这哈结果就称透了
在这里插入图片描述
这里虽然试验成功是因为我这里的printf都是使用了\n换行转义符,这个换行转义符会把printf缓冲区中的所有内容都打印出来,但是如果没有\n, 就有问题了,我这里为了实验,就不要lockf函数,因为没有了lockf函数,按理来说打印的信息是会串在一起的,但是结果变成了这样虽然没有换行,但是也应该串在一起三,而且程序不是每隔一秒打印一次,而是等整个循环执行完了才打印
在这里插入图片描述

Linux进程通信

进程通信的内容还是相当多的,我只是大概了解了一下管道, 命名管道, 还有啥子0, 1, 2,分别是标准输入,标准输出,错误输出,记不清楚了。。
Linux下的进程通信
Linux内核likely()和unlikely()函数

管道

管道图解
从内核源码分析管道
Linux内核分析
浅谈dup和dup2函数
Linux文件描述符
这几篇文章一起看效果最好~

开始我看到pipe(int pid[2])函数的时候,我就很不解,传两个整数过切,为啥会跟文件扯上关系,而且还必须传一个只有两个元素的数组过切,而且每次调用pipe()函数过后,每次fd[0] 和 fd[1]的值都是3 和 4,这些整数其实就是文件描述符,是系统自动分配当前进程中能够使用的最小值的文件描述符的下标。而这些文件描述符就相当于一个数组的下标,这个数组里面的内容就是指针,就如上面文章中的图所讲解的一样
这里面的文件描述符有点意思,每个进程都有自己的文件描述符可以通过在/etc/proc/${进程号}/pd中看到瞬间就对啥子0, 1, 2这三个标准输入,输出,错误输出,有了感性的认识,其实还可以直接vim编辑一哈,还好耍
在这里插入图片描述

自动截图Shell

做操作系统试验的时候,老师喊我们写实验报告(一想到实验报告就感觉恶心,又要截图,又要粘代码,还要写心得体会,最弹得是还要写一段感谢信),因为当时有些人安ubuntu始终有问题,就有人请别人帮忙做的,而且我们老师就是为了防止我们用别人的截图,所以要求我们截图的时候每个人必须用自己的姓名、学号做用户名,然后我就想到整个shell,只用输入一个人的姓名、学号、用户名,所有老师要求的截图都放到一个指定的文件夹中,这样就很爽了

最后虽然成功,但是就我一个人用了,因为我都是最后才交,因为了解这些东西和整这个shell实在是费时间,确实没法我才抵拢了才交,所以也没装成逼,只给宇哥一个人看了一哈。还是把代码记录一哈,以后自己看。

#!/bin/bash
id=$1
name=$2
username=$3
shiyan='实验'

function tt(){
	printf "\033[1;32m${username}@${id}\033[0m:\033[1;34m~/Desktop/
									${tempshiyan}/${name}\033[0m$ ";
}

function out(){
	tempshiyan=${shiyan}${count}
	tt
	echo  ${commond}
}
imagepath="../share/testtest"

count=1;
path="backup/1实验一"
clear
#----------------------------------------
	commond="gcc copyfread1024 -o copyfread1024.exe"
	out
	commond="time ./copyfread1024 copy.txt to.txt"
	out
	time ./${path}/copyfread1024.exe ${path}/copy.txt ${path}/to.txt

	commond="gcc copyfread -o copyfread.exe"
	out
	commond="time ./copyfread copy.txt to.txt"
	out
	time ./${path}/copyfread.exe ${path}/copy.txt ${path}/to.txt

	commond="gcc copyread1024.c -o copyread1024.exe"
	out
	commond="time ./copyfreadcopy.exe copy.txt to.txt"
	out
	time ./${path}/copyread1024.exe ${path}/copy.txt ${path}/to.txt

	commond="gcc copyread.c -o copyread.exe"
	out
	commond="time ./copyread.exe copy.txt to.txt"
	out
	time ./${path}/copyread.exe ${path}/copy.txt ${path}/to.txt
	
	sleep 1
	imagename=$(date +%N)
	scrot -u ${imagepath}/test${count}/${imagename}.png
	clear

	commond="cat /proc/stat"
	out
	cat /proc/stat
	sleep 1
	imagename=$(date +%N)
	scrot -u ${imagepath}/test${count}/${imagename}.png
	clear

	./showcurse
	reset
	reset

count=2;
path="backup2/linux-source-4.11.0"
#----------------------------------------
	cd ${path}
	commond="sudo make mrproper"
	out
	make mrproper
	commond="sudo make clean"
	out
	sudo make clean
	commond="sudo make"
	out
	make
	commond="sudo make modules_install"
	out
	make modules_install
	commond="sudo make install"
	out
	make install
	cd ../../
		
	sleep 2
	imagename=$(date +%N)
	scrot -u ${imagepath}/test${count}/${imagename}.png
	clear
	clear

	path="backup2"
	commond="./testcall"
	out
	./${path}/testcall
	./${path}/testcall
	./${path}/testcall
	
	commond="./testcopy"
	out
	./${path}/testcopy
	commond="cat aim.txt"
	cat ${path}/aim.txt

	sleep 1
	imagename=$(date +%N)
	scrot -u ${imagepath}/test${count}/${imagename}.png
	clear
	clear

count=3;
path="backup3/fork_t"
#----------------------------------------
	commond="gcc fork.c -o fork"
	out
	commond="./fork"
	./${path}/fork
	commond="gcc fork.c -o fork"
	out
	commond="./fork"
	out
	./${path}/fork
	sleep 1
	imagename=$(date +%N)
	scrot -u ${imagepath}/test${count}/${imagename}.png
	clear
	clear

	path="backup3/process_t"
	commond="gcc process.c -o process"
	out
	commond="./process.c"
	out
	./${path}/process
	sleep 5
	imagename=$(date +%N)
	scrot -u ${imagepath}/test${count}/${imagename}.png
	clear
	clear

	path="backup3/multi_process"
	commond="gcc single_process.c -o single_process"
	out
	commond="./single_process"
	./${path}/simgle_process
	commond="gcc multi_process.c -o multi_process"
	out
	commond="./multi_process"
	out
	./${path}/multi_process
	commond="gcc multi_pthread.c -o multi_pthread"
	out
	commond="./multi_pthread"
	out
	./${path}/multi_pthread
	imagename=$(date +%N)
	scrot -u ${imagepath}/test${count}/${imagename}.png
	clear
	clear



count=4;
path="backup4"
#----------------------------------------

	commond="gcc server.c -o server"
	out
	commond="gcc client.c -o clien"
	out 
	commond="./server &"
	out
	commond="./client "
	out
	./showserver ${name} ${id}
	clear

	commond="gcc test.c -o test -pthread"
	out
	commond="./test"
	out 
	./showtest

说实话这个shell还是有一些困难,这是我们要截图的一个例子:在这里插入图片描述

  1. 第一就是用户名的问题,上面说了老师要求我们用自己的姓名、学号做用户名,所以我第一个思路就是在shell里面创建用户也就是用useradd,还在网上找了半天,才有个办法把验证密码解决的,但是!!!su的时候就不得行了,反正我也没搞清楚咋回事,就是不能在shell中切换用户,当时脑壳都整痛了,然后上床休息了一哈,海耶突然灵机一动!,反正都是打印,我就直接手动把想打印的用户名、主机名都打印出来就完了三。你可能会说,用户名主机名都是那种颜色特别的字体,咋整喃,然后我就且找,shell还真的可以改字体!!,爽,就是这一段print"\033[1;32m${username}@${id}\033[0m:\033[1;34m~/Desktop/${tempshiyan}/${name}\033[0m$ ";啥子\033这些都是颜色~,然后路径名那些都自己打印
  2. 第二就是有一个截图是在运行一个程序的时候,我截图都是通过一个命令,在shell中可以直接调,但是在运行另外一个程序的时候我咋个截图喃?而且还要把时间搞好,这时候上面学到的进程通信的技术就派上用场了,exec函数族waitsignalfork一个都不能少,说实话现在想起有点成就感 ?
  3. 还有就是编译内核的时候咋个办喃?这个一编译起码都是一个小时,咋个截,不可能在shell头写sleep(60 * 60)三,这时候就要用到我之前写的这篇文章编译Linux内核的经验,方法就是自己Makefile文件改了,哎呀,反正老师又不得细看,随便写点编译信息就脱手
  4. 最后就是因为每个地方都要打印命令,重复代码很多,这时候有用到了军儿哥传授的高内聚低耦合,解耦和 ?,开个玩笑~

确实当时截图的时候,那种效果还是多炫的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值