Linux编程—系统编程(进程)

库和C程序存储分配

在之前先记录一个库文件的制作方法,它基于分文件编程之上,也是分文件,模块化的延展。
关于库文件的博文推荐
库相关的理论性博文

分文件的编程思想:主要逻辑代码main.c 功能实习代码 xxx.c 包含功能函数和相关信息、参数的 xxx.h
main.c 中包含 “xxx.h”
gcc mian.c xxx.c -I ./ -o test
库文件命名
库文件分为静态库(.a文件)和动态共享库(.so文件);
静态库的制作:

首先生成.o文件
gcc xxx.c -c //编译C文件生成OBJ对象文件
ar rcs libxxx.a xxx.o xxx.o//将OBJ文件加载到一起生成静态库.a文件

动态库的制作:

gcc -shared -fpic xxx.c xxx.c -o libxxx.so //将C功能程序集成到动态库.so文件中

库文件的使用:
静态库—gcc main.c -l静态库文件名 -I ./ -L ./ -o test1 //编译包含声明了库函数头文件的主程序,-l链接库名,-I大写的i指定包含的头文件在当前路径./ -L指定的库在当前路径./ -o为生成的可执行程序命名为test1。
动态共享库—gcc main.c -l动态库名 -I ./ -L ./ -o test2 //动态库的使用和静态库一样,区别在静态库在链接的时候已经把功能程序加了进去,而动态共享库的使用虽然链接了库但是功能程序没加进去,它是在执行的过程中实时从动态库中提取功能。所以直接运行使用动态库的可执行程序可能会出现错误。通常需要把相应的动态库文件放到系统指定文件夹mv libxxx.so /usr/lib 或者配置环境变量库函数名:砍头(去掉lib)去尾(去掉.a或.so的后缀)

动态库环境变量配置
终端输入export列出环境变量

export LD_LIBRARY_PATH="这里放动态库的路径"

将环境变量与shell脚本写在一起
vi test.sh
将上面环境变量的配置和执行加载动态库的执行程序写在一起。线程中有提到
关于分别用动态库和静态库生成的同一程序,适用 du 或者 size 指令即可看出区别

#C程序的存储空间
参考优质博文
C程序的内存空间存储分配
下方内容取自 CSDN博主「编码赚钱娶老婆」的原创文章 ,感谢博主的分享
原文链接:https://blog.csdn.net/weixin_39923782/article/details/105487735
正文段(code):这是有CPU执行的机器指令。正文段是可共享的,所以即使所示频繁执行程序(文本编辑器,C编译器、shell等)在存储器也只需要有一个副本,另外正文段常常是只读的,以防止程序出现意外而修改其指令;
初始化数据段(data):通常此段称为数据段,它包含了需明确的赋值的变量像全局变量 int maxcount = 99;那么maxcount 变量就放在数据段
未初始化的数据段(bss):通常称为bss段,像全局变量 long sum[];sum就是存储早bss段
栈 (stack):自动变量以及每次函数调用时所保存的信息都放在此段,像函数的参数,函数体内变量,返回值。栈顶在低地址,栈底在高地址。
堆区(heap):通常在堆中进行动态分配像使用malloc函数分配空间。
fork()创建的父子进程在内存空间上是写时拷贝,vfork()创建的 父子进程中子进程直接使用父进程的内存,不进行拷贝

进程

概念:进程是程序的一次运行活动
补充:Linux下使用ps -aux|grep a.out 查看进程,top相当于任务管理器 kill 进程ID(结束相应的进程)
进程ID中 0为交换进程,1为init系统初始化进程
父进程创建子进程的写实拷贝。进程的退出状态可以被收集并用宏解析出来。
exec族函数借鉴博文
exec族函数同门借鉴
API:

#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <stdio.h>

pid_t pid;//定义一个存放进程ID号的变量
pid_t fork(void);//创建进程1
pid_t vfork(void);//创建进程2,与1的区别在于如果创建多个进程,父进程会等待子进程退出才运行,而fork()创建的父子进程相互争着运行。
pid_t wait(int *wstatus);//进程等待,用于等待子进程退出
pid_t waitpid(pid_t pid, int *wstatus, int options);//可设选项的进程等待
pid_t getpid(void);//获取当前进程的ID进程标识符
pid_t getppid(void);//获取当前进程的父进程ID
exit();//退出进程(标准C库)  exit为正常退出
_exit(); _Exit();//(系统调用)
//异常退出
//abort()

//执行系统指令的API(exc族函数)
  int execl(const char *path, const char *arg, ... /* (char  *) NULL */);
  int execlp(const char *file, const char *arg, .../* (char  *) NULL */);
  int execle(const char *path, const char *arg, .../*, (char *) NULL, char * const envp[] */);
  int execv(const char *path, char *const argv[]);
  int execvp(const char *file, char *const argv[]);
  int execvpe(const char *file, char *const argv[],char *const envp[]);

int system(const char *command);//参数为Linux下的指令或可执行文件名
FILE *popen(const char *command, const char *type);
int pclose(FILE *stream);//popen执行指令或程序,并返回一个指向存储结果的文件指针,pclose关闭文件指针
int chdir(const char *path);
int fchdir(int fd);//在程序中进入某个文件夹

进程退出及其状态收集

参考博文
在wait函数中传参一个整型指针去接收进程退出的状态值,想要看到正确的状态值需要使用宏解析.

fork()模拟客户端介入服务端的场景

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

int main(void)
{
	int passwd;
	pid_t pid;
	pid=getpid();//获取最初进程的ID
	printf("server ID:%d\n",pid);
	while(1)
	{
		passwd=0;
		printf("please input passwd :\n");
		scanf("%d",&passwd);
		getchar();
		if(passwd==1)
		{
			//如果这里调用vfork那么父进程就不在等待按键输入,而阻塞。
			//子进程退出,父进程没有wait,子进程变成僵尸进程。
			//父进程在子进程结束前先退出,子进程被init进程收留成为孤儿进程。
			if(fork()==0)//调用fork会返回两次,父进程那次返回子进程的ID号(非负整数),子进程那次返回0;
			//fork创建进程失败返回-1;
			{
				while(1)
				{
					sleep(2);
					printf("server ID:%d client ID:%d\n",getppid(),getpid());
				}
			}
		}
	}
	return 0;
}

DIY—FTP服务器程序的指令执行部分

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#define ZL 68
#define PT 3000
#define YES 1
#define NO 0

char order[ZL];
char output[PT];

void display()//》》》》》》》》》》》》》显示标题
{
	int i;
	putchar('\n');
	for(i=0;i<5;i++)
	{
		if(i==2)
		{
			printf("$*************Welcome To FTP !!!**************$\n");
		}else{
			printf("$*********************************************$\n");
		}
	}
}

void mygets(char *p)//>>>>>>>>>>>>>>>>指令输入函数
{
	if(p==NULL)return;
	while(*p=getchar())
	{
		if(*p=='\n')break;
		else p++;
	}
	*p='\0';
}

int orderJudge()//>>>>>>>>>>>>>>>>>>>>>>>>>>>>指令鉴别
{
	memset(order,0,ZL);
	printf("order:");
	mygets(order);
	if(!strcmp(order,"ps"))return YES;
	else if(!strcmp(order,"ls"))return YES;
	else if(!strcmp(order,"ls -l"))return YES;
	else if(!strcmp(order,"pwd"))return YES;
	else if(!strcmp(order,"tree"))return YES;
	else if(!strcmp(order,"date"))return YES;
	else if(!strcmp(order,"ifconfig"))return YES;
	else if(strstr(order,"cd "))return YES;
	else if(strstr(order,"du"))return YES;
	else if(strstr(order,"cat "))return YES;
	else if(!strcmp(order,"quit"))
	{
		printf("$*******************See You*******************$\n");
		exit(1);
	}
	else return NO;
}

void popenexec()//>>>>>>>>>>>>>>>>>>>>>>>>>>指令执行
{
	char *cdorder=NULL;
	if(strstr(order,"cd "))
	{
		cdorder=order+strlen("cd ");
		if(chdir(cdorder)==-1)
		{
			perror("cd");
			return;
		}
	}else{
		FILE *fp=NULL;
		fp=popen(order,"r");
		if(fp==NULL)
		{
			printf("$**************exec order fail!!**************$\n");
			return;
		}else{
			memset(output,0,PT);
			fread(output,sizeof(char),PT,fp);
			printf("result:\n");
			printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
			printf("%s",output);
			if(!strcmp(order,"ls -l"))putchar('\n');
			printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
			pclose(fp);
		}
	}
}

int popenOrder()
{
	if(orderJudge()==YES)
	{
		popenexec();
	}else{
		printf("$*sorry,haven't the order.please input again.*$\n");
	}
}

int main(void)
{
	display();
	while(1)
	{
		popenOrder();
	}
	return 0;
}

环境变量的配置

例:将a.out配置为环境变量
1.在a.out文件所在的目录下使用pwd打印出可执行程序的路径
2.使用echo $ PATH 指令输出环境变量
3.export PATH=环境变量(到games:前+a.out的路径,最后回车即可
或者 export PATH=$PATH:+pwd输出的路径
执行到第3步,环境变量在当前控制台有效。如果想配置长期有效则:
将第3步的内容写入~/.bashrc中重启或者source ~/.bashrc即可

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值