shell C语言编程

1、编译优化

//代码

#include <stdio.h>
int main(void)
{
   
double counter;
double result;
double temp;
for (counter = 0; counter < 2000.0 * 2000.0 * 2000.0 / 20.0 + 2020;
counter += (5 -1) / 4) {
   
temp = counter / 1979;
result = counter;
}
printf(Result is %lf\\n, result);
return 0;
}

gdb调试:

优化后
请添加图片描述

未优化

请添加图片描述

优化分析:

  • 代码分析

请添加图片描述

  • 执行分析
    请添加图片描述

  • 大小分析

请添加图片描述

区别:-O优化会改变文件大小,会更小一点。优化后的代码执行时间会更短;优化后的代码会把数据全部存入xmm寄存器,计算时直接从寄存器读取数据;未优化的代码会把一些数据放在栈中来读取。栈中读取和寄存器读取,显然寄存器会更快。

makefiel

一个工程中的源文件不计数,其按类型功能模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。

2、文件基本操作编程

使用Linux系统调用编写一个完成文件拷贝的C程序。比较拷贝得到的文件与源文件的大小和内容(命令diff,cmp)。

代码

#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include<unistd.h>

int main(){
int f1,f1_l,f2;	//f1:文件a.txt的句柄;f2:文件b.txt的句柄;f1_l:a.txt文件内容的长度。
char buf[1024]={};//这个用于暂时存储被复制的文件内容

//打开源文件,读取文件内容
f1=open("a.txt",O_RDWR);
f1_l=read(f1,buf,1024);

//这里打开目标文件,如果没有就创建一个,且权限为777,然后将内容复制到目标文件
f2=open("b.txt",O_RDWR | O_CREAT,0777);
write(f2,buf,f1_l);

close(f1);
close(f2);

}

执行结果:

请添加图片描述

​ 用ls去查看,发现文件大小没有不同,只是两者权限不同。权限设置的是777,但是由于用户的默认权限掩码,

请添加图片描述

0022,所以创建出来的权限就是0777-0022=0755。

​ 用diff去比较,

请添加图片描述

diff会针对文本内容逐行进行对比,如果有不同就会显示出这有差别的两行,这里看到文本内容上并没有什么差别。

请添加图片描述

​ 用cmp去对比,

请添加图片描述

cmp会逐个字符去比较,会告诉有差异的字符的位置,第几行第几个字符。不加参数的情况下它只会显示出第一个有差异的位置。-l参数会帮助显示出所有有差异的位置。这里也没有不同。

请添加图片描述

编写C程序完成:创建一个新文件,输入一段数据,然后随机移动指针接着插入一段数据。完成后,查看该文件的大小和内容。怎样获取当前文件的读写指针位置?

代码

#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>

int main(){
   
    int fd,loc;
    char name[10]="\0";
    char context[1024]="\0";
    char tip[]="mkanewdir!";//插入字符串内容

    //创建一个新文件
    printf("文件名:");
    gets(name);
    fd=creat(name,0777);

    //输入一段内容写入新文件中
    printf("内容:");
    gets(context);
    write(fd,context,sizeof(context));

    //插入字符串
    lseek(fd,2,SEEK_SET);
    write(fd,tip,strlen(context)+8);
    

    //读取文件指针位置
    loc=lseek(fd,0,SEEK_CUR);
    printf("当前文件读写指针的位置:%d。",loc);
    close(fd);
}

获取字符串长度的话就是lseek,SEEK_CUR锁定到当前位置,偏移量为0,就可以得到当前位置了。这里有尝试用tell函数,但是编译时显示没有定义这样一个函数。不知道是我的gcc太老了还是啥。

请添加图片描述

请添加图片描述

这里文件的大小就是总的字符串长度。

3、编写拷贝命令,实现文件或目录的复制

#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/vfs.h>

long int dir_list[100][100][100];
long int dir_dst[100][100][100];
int loc=0,i=0,count=0,off=0;
int alow,sum=0;

int ls();
void copy_file();
void copy_dir();
void samename(mode_t mode);
void counter();
int main(int num,char* name[])
{
   
	struct stat fl_str,fl_dst;
	struct statfs size;
	
	sprintf(dir_list[0][0],name[1]);//参数存如数组中
	sprintf(dir_dst[0][0],name[2]);

	stat(dir_list[0][0],&fl_str);
	stat(dir_dst[0][0],&fl_dst);

	

	samename(fl_str.st_mode);//同名判断
	statfs(dir_dst[0][0],&size);
	alow=4*size.f_bavail;
	switch(num)
	{
   
		case 3://文件复制
			if(S_ISREG(fl_str.st_mode)&&((fl_str.st_size/1000)<alow))
			{
   
				copy_file();
			}
			else
				printf("磁盘大小不足,复制中止!");
			break;
		case 4://目录复制
			if(S_ISDIR(fl_str.st_mode)&&!strcmp(name[3],"-r"))
			{
   
				ls();
			}
			else
				printf("复制目录格式有误!复制中止!\n格式:源路径 目标路径 -r");
			break;
	}
	
}

int ls()//遍历目录,递归复制
{
   
	char dst[100];
  	DIR* dir_ptr[100];
	struct dirent* direntp;    
	struct stat type;

	while(off<2)
	{
   
		while((dir_ptr[loc] = opendir(dir_list[loc][0]))!=NULL)
		{
   
			while((direntp = readdir(dir_ptr[loc])) != NULL)
			{
   
				if(!strcmp(direntp->d_name,"..")||!strcmp(direntp->d_name,"."))
				{
   
					continue;
				}
				sprintf(dir_list[loc][++i],"%s/%s",dir_list[loc][0],direntp->d_name);
				sprintf(dir_dst[loc][i],"%s/%s",dir_dst[loc][0],direntp->d_name);
				stat(dir_list[loc][i], &type);
				if(S_ISREG(type.st_mode))
				{
   
					if(off==0)
						sum+=type.st_size;
					else
						copy_file();
				}
				else if(S_ISDIR(type.st_mode))
				{
   
					
					++count;
					strcpy(dir_list[count][0],dir_list[loc][i]);
					strcpy(dir_dst[count][0],dir_dst[loc][i]);
					if(off==0)
						sum+=type.st_size;
					else
						copy_dir();
				}
			}
			if(count>=loc)
			{
   
				loc++;
				i=0;
			}
		}
		switch(off)
		{
   
			case 0:
				if((sum/1000)>alow)
				{
   
					perror("ERROR:磁盘容量不足,停止复制!\n");
					_exit(2);
				}
				else
					printf("复制成功!\n目录大小:%2dkb,可使用剩余磁盘容量:%2dkb。\n",sum/1000,alow-sum/1000);
				break;
			case 1:break;	
		}
		off++;
		loc=0,i=0,count=0;
	}
}

void copy_file()//复制文件
{
   

	int fl_str,fl_dst,len;
	char context[10240];

	fl_str=open(dir_list[loc][i],O_RDONLY);
	len=read(fl_str,context,10240);
	
	fl_dst=open(dir_dst[loc][i],O_RDWR|O_CREAT,0644);
	write(fl_dst,context,len);
	close(fl_str);
	close(fl_dst);
}

void copy_dir()//复制目录
{
   
	mkdir(dir_dst[loc][i],0777);
}

void samename(mode_t mode)//同名判断
{
   

	if(access(dir_dst[0][0],F_OK)==0)
	{
   
		perror("ERROR:有同名文件存在,停止复制!\n");
		_exit(2);
	}
	else if(S_ISREG(mode))
	{
   
		creat(dir_dst[0][0],0644);
	}
	else if(S_ISDIR(mode))
	{
   
		copy_dir();
	}
}
//这个代码网上转载
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>

int is_dir(char *path);                         //判断是否是目录  是返回1 否则返回0
int copy_file(char *srcPath, char *destPath);   //复制文件  成功返回0 否则返回 -1
int copy_folder(char *srcPath, char *destPath); //复制文件夹  成功返回0 否则返回 -1

int main(int argc, char *argv[]) // argv[1] 源文件  argv[2] 目标文件
{
   
    if (argc != 3)
    {
   
        printf("Usage srcfile destfile\n");
        return -1;
    }
    char *srcPath = argv[1];
    char *destPath 
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
实验一 linux 内核编译及添加系统调用 设计目的 Linux 是开源操作系统,用户可以根据自身系统需要裁剪、修改内核,定制出功能更加 合适、运行效率更高的系统,因此,编译 linux 内核是进行内核开发的必要基本功。 在系统中根据需要添加新的系统调用是修改内核的一种常用手段,通过本次实验,读 者应理解 linux 系统处理系统调用的流程以及增加系统调用的方法。 内容要求 (1) 添加一个系统调用,实现对指定进程的 nice 值的修改或读取功能,并返回进程最 新的 nice 值及优先级 prio。建议调用原型为: int mysetnice(pid_t pid, int flag, int nicevalue, void __user * prio, void __user * nice); 参数含义: pid:进程 ID。 flag:若值为 0,表示读取 nice 值;若值为 1,表示修改 nice 值。 Prio、nice:进程当前优先级及 nice 值。 返回值:系统调用成功时返回 0,失败时返回错误码 EFAULT。 (2) 写一个简单的应用程序测试(1)中添加的系统调用。 (3) 若程序中调用了 linux 的内核函数,要求深入阅读相关函数源码。 实验二 linux 内核模块编程 设计目的 Linux 提供的模块机制能动态扩充 linux 功能而无需重新编译内核,已经广泛应用在 linux 内核的许多功能的实现中。在本实验中将学习模块的基本概念、原理及实现技术,然后利 用内核模块编程访问进程的基本信息,从而加深对进程概念的理解、对模块编程技术的掌 握。 内容要求 (1) 设计一个模块,要求列出系统中所有内核线程的程序名、PID 号、进程状态及 进程优先级。 (2) 设计一个带参数的模块,其参数为某个进程的 PID 号,该模块的功能是列出该 进程的家族信息,包括父进程、兄弟进程和子进程的程序名、PID 号。 (3) 请根据自身情况,进一步阅读分析程序中用到的相关内核函数的源码实现。 实验四 linux 进程管理 设计目的 (1) 熟悉 linux 的命令接口。 (2) 通过对 linux 进程控制的相关系统调用的编程应用,进一步加深对进程概念的理解, 明确进程和程序的联系和区别,理解进程并发执行的具体含义。 (3) 通过 Linux 管道通信机制、消息队列通信机制、共享内存通信机制的使用,加深 对不同类型的进程通信方式的理解。 (4) 通过对 linux 的 Posix 信号量的应用,加深对信号量同步机制的理解。 (5)请根据自身情况,进一步阅读分析相关系统调用的内核源码实现。 设计内容 (1)熟悉 linux 常用命令:pwd,useradd,passwd, who, ps, pstree, kill, top, ls, cd, mkdir, rmdir, cp, rm, mv, cat, more, grep 等。 (2) 实现一个模拟的 shell: 编写三个不同的程序 cmd1.c,cmd2.c,cmd3.c,每个程序的功能自定,分别编译成可执 行文件 cmd1,cmd2,cmd3。然后再编写一个程序,模拟 shell 程序的功能,能根据用户输 入的字符串(表示相应的命令名),去为相应的命令创建子进程并让它去执行相应的程序,而父进程则等待子进程结束,然后再等待接收下一条命令。如果接收到的命令为 exit,则父 进程结束;如果接收到的命令是无效命令,则显示“Command not found”,继续等待。 (3) 实现一个管道通信程序: 由父进程创建一个管道,然后再创建 3 个子进程,并由这三个子进程利用管道与父进程 之间进行通信:子进程发送信息,父进程等三个子进程全部发完消息后再接收信息。通信的 具体内容可根据自己的需要随意设计,要求能试验阻塞型读写过程中的各种情况,测试管道 的默认大小,并且要求利用 Posix 信号量机制实现进程间对管道的互斥访问。运行程序,观 察各种情况下,进程实际读写的字节数以及进程阻塞唤醒的情况。 (4) 利用 linux 的消息队列通信机制实现两个线程间的通信: 编写程序创建两个线程:sender 线程和 receive 线程,其中 sender 线程运行函数 sender(), 它创建一个消息队列,然后,循环等待用户通过终端输入一串字符,将这串字符通过消息队 列发送给 receiver 线程,直到用户输入“exit”为止;最后,它向 receiver 线程发送消息“end”, 并且等待 receiver 的应答,等到应答消息后,将接收到的应答信息显示在终端屏幕上,删除 相关消息队列,结束程序运行。Receiver 线程运行 rece

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿拉垮神登

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值