嵌入式学习总结----c基础、c高级、数据结构、IO与进程、网络编程

本文介绍了Linux环境下的C语言基础,包括Ubuntu系统使用、终端操作、vim编辑器的快捷键,以及C语言中的基本数据类型、存储类型和指针概念。后续内容涉及数据结构、进程管理和网络编程(TCP/IP和UDP)的概述。
摘要由CSDN通过智能技术生成
c基础

这部分初步学习和了解Linux的使用:

       嵌入式开发 环境搭建: 基于Linux 平台的 C语言编程 

       Linux系统:  是一个操作系统 类似于Windows   侧重于 字符界面 终端命令行模式

       Ubuntu系统: 是 一类 Linux 系统  图形界面 与 Windows类似  对新手友好

环境使用:

        Ubuntu系统 使用  终端 字符界面

        打开终端  右键 打开终端   或 快捷键   ctrl + alt + t   

        在同一个窗口中 打开多个终端 ctrl + shift + t 

vim的使用:

         进入vim 处于命令模式:该模式下任何按键都认为是命令

dd 剪切光标所在行 
yy 复制光标所在行 
p  粘贴
u  撤销 
x  删除光标所在字符

i: 在光标 前 插入 
a: 在光标 后 插入 
o: 在光标 下 新建一行 插入 

esc 退出插入模式

底行模式:  输入 : 进入 
:wq  保存退出 
:w   保存但不退出 
:q!  退出且不保存

vim快捷键:                   
1.全选:ggVG
2.跳转到文本最后一行:shift+g
 3.跳转到文本第一行:gg
4.跳转到光标所选行的行尾位置:shift+4
5.gg=G即可对齐

一个简单代码示例:

#include <stdio.h>  //头文件  标准输入

int main(){  //主函数 一个c程序的入口
    printf("hello world!\n");  //在终端输入字符 "hello world!\n"
    return 0;  //退出
}

ls -l  显示文件的详细信息:-rwxrwxr-x 1 xwq xwq 8712 6月  29 14:25 a.out

   - 表示文件的类型  普通文件  d 表示目录文件    文件夹 

 C语言中的 基本数据类型:  

 char   字符类型 、unsigned char  无符号字符类型 、signed   char  有符号字符类型

short 半指类型 短整 、int   整型 、long  长整型  

float  单精度 浮点型、double 双精度、bool 布尔类型

存储类型:    
      存储相关的: auto 自动类型(缺省值)  根据变量定义的位置 来自动分配空间 
      const 修饰变量 改变存储位置到  常量区 或 限制变量的写权限 
      extern      外部引用存储 
      register    寄存器存储 
      static      静态存储      
    
局部变量:  局部的作用域(能访问到该变量的代码区域)  与 局部的 生命周期 (存在的时间)
    在代码块内{}定义的 变量   局部变量存放于 栈区, 有程序运行过程中
    代码块开始时 自动分配 与 释放  代码块结束时   

全局变量:  全局的 作用域(任何位置都可以访问) 有 全局的 生命周期  
    在函数外, 创建的变量 ,存放于 静态区 
    程序开始时, 就被创建了   直到程序结束  才会释放 

使用三目运算符 求 x,y,z中的最大值 
    max = x>y?(x>z?x:z):(y>z?y:z);

c高级

  这一部分是Linux系统基础

  • .指针变量   本质是一个变量  存放的是一个 内存地址   
  • 内存地址   是一个常量

指针数组 与 二级指针: 

指针数组:  一个数组 其元素是 指针 

const char * ps[5];  常量字符串指针数组 
const char    **p = ps;  二级指针 

//指针方式遍历
for(p=ps ; p < ps+5 ; p++)  //p+1  移动一个 const char    * 类型长度 
{
    printf("%s ", *p); 
}
printf("\n");

  • 结构体变量使用:

    结构体成员运算符   .  
    结构体变量.成员名 

   typedef  关键字 :  类型取别名 

以下是计算数组中的最大元素及其下标值的代码:

#include <stdio.h>
	
void findmax ( int s[ ], int t, int *k )
	{
        int  i;
        *k = 0;

        for ( i = 1; i < t; i++)
        {
           if ( s[*k] < s[i] ) *k = i;
        } 

        return ;
	}
	
int main (void)
{
		int a[10] = {12, 23, 34, 45, 56, 67, 78, 89, 11, 22}, k;
		findmax ( a, 10, &k );
		printf ( “ 最大元素为:%d, 其下标值为:%d\n”, a[k], k );
	    return 0;
}
数据结构

这一部分学习如何更好的写程序

  • 数据结构:

        是指计算机存储和组织数据的一种方式,相互之间存在一种或多种特定关系的集合

  • 常见的时间复杂度:

(1)常量阶____O(1)

(2)线性阶____O(n)

(3)平方阶___O(n^2)

(4)对数阶___O(logn)

  • 空间复杂度:表示随问题规模n的增大,算法执行时占用的内存增长率和f(n)的增长率相同
  • 线性表的存储方式有两种:顺序存储、链式存储
  • 数组分为两种:

静态数组例如:
            int arr[10];

动态数组例如:
                    #define  maxsize  10
                    int  *p=(int *)malloc(maxsize *sizeof(int))
                memset(void *P,int n,sizeof(*P))//常用它去清空内存空间

以下是创建十个结点的完全二叉树的代码:

#include <stdio.h>
#include <stdlib.h>

// 定义二叉树节点结构
struct Node {
    int data;
    struct Node *left;
    struct Node *right;
};

// 创建新节点
struct Node *createNode(int data) {
    struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
    newNode->data = data;
    newNode->left = NULL;
    newNode->right = NULL;
    return newNode;
}

// 创建完全二叉树
struct Node *createCompleteBinaryTree(int arr[], int n, int i) {
    if (i >= n) {
        return NULL;
    }

    struct Node *root = createNode(arr[i]);

    // 递归创建左子树和右子树
    root->left = createCompleteBinaryTree(arr, n, 2*i + 1);
    root->right = createCompleteBinaryTree(arr, n, 2*i + 2);

    return root;
}

// 先序遍历二叉树
void preOrderTraversal(struct Node *root) {
    if (root != NULL) {
        printf("%d ", root->data);
        preOrderTraversal(root->left);
        preOrderTraversal(root->right);
    }
}

int main() {
    int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    int n = sizeof(arr) / sizeof(arr[0]);

    struct Node *root = createCompleteBinaryTree(arr, n, 0);

    printf("先序遍历结果:");
    preOrderTraversal(root);

    return 0;
}

IO与进程

这一部分学习的是应用层内容

进程是资源管理的最小单位

线程是资源调度的最小单位

程序是进行某项活动或过程所规定的途径

fork()分叉 一个进程的诞生,由从父进程调用fork()而来。

创造出来后的状态是就绪态,等待资源,睡眠态或挂起

无名管道(PIPE)

只能用于亲缘进程(fok()诞生),无名管道没有名字,只能亲缘进程中去继承文件描述符。

有名管道(FIFO)

有名字的文件,所以每个进程都能打开,针对所有没有亲缘关系的进程

消息队列(MSG)

提供一种带有数据标识的特殊管道,使得每一段被写入的数据都变成带标识的 消息,读取该段消息的进程只要指定这个标识就可以正确地读取,而不会受到其他消息的干 扰,从运行效果来看,一个带标识的消息队列,就像多条并存的管道一样。

共享内存(SHM,即 SHared Memory)

是效率最高的 IPC ,因为他抛弃了内核这个“代理人”,直截了当地将一块裸 露的内存放在需要数据传输的进程面前,让他们自己搞,这样的代价是:这些进程必须小心 谨慎地操作这块裸露的共享内存,做好诸如同步、互斥等工作,毕竟现在没有人帮他们来管 理了,一切都要自己动手。也因为这个原因,共享内存一般不能单独使用,而要配合信号量、 互斥锁等协调机制,让各个进程在高效交换数据的同时,不会发生数据践踏、破坏等意外。

信号量 (SEM)

Linux 中用到的信号量有 3 种:ststem-V 信号量、POSIX 有名信号量和 POSIX 无名信号量

以下是写入数据的代码:

#include <stdio.h>
#include <fcntl.h>              
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>           
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/msg.h>
#include <sys/sem.h>
#include <semaphore.h>
#include <signal.h>

sem_t *space;
sem_t *data;

void trap_signal()
{
	sem_close(space);
	sem_close(data);
	
	sem_unlink("/mysemspace");
	sem_unlink("/mysemdata");
	
}

int main()
{
	int shmid = shmget(ftok("./",1), 2,IPC_CREAT | 0666);//共享内存的大小必须是偶数,实际上在本代码中只需要1个
	
	char *p = shmat(shmid, NULL, 0);//映射
	
	space = sem_open("/mysemspace", O_CREAT, 0666, 1);
	data = sem_open("/mysemdata", O_CREAT, 0666, 0);
	
	char *msg = "0123456789";
	int i = 0;
	
	signal(SIGINT, &trap_signal);
	
	while(1)
	{
		//写入数据
		sem_wait(space);//空间-1  0个
		sleep(1);
		memcpy(p, msg+i, 1);
		
		sem_post(data);//数据+1   1个
		
		i = (i+1)%10;
		
	}
	
}

以下是读数据的代码:

#include <stdio.h>
#include <fcntl.h>              
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>           
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/msg.h>
#include <sys/sem.h>
#include <semaphore.h>
#include <signal.h>

sem_t *space;
sem_t *data;

void trap_signal()
{
	sem_close(space);
	sem_close(data);
	
	sem_unlink("/mysemspace");
	sem_unlink("/mysemdata");
	
}

int main()
{
	int shmid = shmget(ftok("./",1), 2,IPC_CREAT | 0666);//共享内存的大小必须是偶数,实际上在本代码中只需要1个
	
	char *p = shmat(shmid, NULL, 0);//映射
	
	space = sem_open("/mysemspace", O_CREAT, 0666, 1);
	data = sem_open("/mysemdata", O_CREAT, 0666, 0);
	
	signal(SIGINT, &trap_signal);
	
	while(1)
	{
		//读数据
		sem_post(space);
		
		fprintf(stderr, "%c", *p);
		
		sem_wait(data);
		
	}
	
}
网络编程

这一部分学习的是应用层内容

tcp是一个面向连接,安全,流式协议。

步骤:

1.创建套接字

//创建套接字
	int sock_fd = socket(PF_INET,SOCK_STREAM,0);

2.绑定

//绑定地址(IP+PORT)
	struct sockaddr_in srvaddr;
	
	srvaddr.sin_family = PF_INET;//地址族
	//端口
	srvaddr.sin_port = htons(10000);	//端口一般取5000以上	
	//IP地址
	srvaddr.sin_addr.s_addr = INADDR_ANY;//将文本字符串转换为32位无符号网络地址
	
	bind(sock_fd,(struct sockaddr *)&srvaddr,sizeof(srvaddr));

3.监听

//设置监听套接字
	listen(sock_fd,4);

4.等待连接

//等待客户端连接
		printf("等待连接\n");

		conn_fd = accept(sock_fd,(struct sockaddr *)&caddr,&addrlen);
		
		printf("[%u]连接成功\n",port);

5.通信

while(1)
		{
			char msg[100];

			bzero(msg,100);
			recv(conn_fd,msg,100,0);
			
			if(strcmp(msg, "quit\n") == 0)//quit
			{
				printf("断开连接\n");
				break;
			}
			printf("recv:%s\n",msg);
		}

6.关闭套接字

//关闭套接字
	close(conn_fd);
	close(sock_fd);

UDP是一种不可靠的、无连接的、数据报服务。

步骤:

1.创建套接字

//创建套接字
	int sock_fd = socket(PF_INET,SOCK_DGRAM,0);

2.绑定

//绑定地址(IP+PORT)
	struct sockaddr_in srvaddr, cliaddr;
	
	srvaddr.sin_family = PF_INET;//地址族
	//端口
	srvaddr.sin_port = htons(5555);	//端口一般取5000以上	
	//IP地址
	srvaddr.sin_addr.s_addr = INADDR_ANY;//将文本字符串转换为32位无符号网络地址
	
	bind(sock_fd,(struct sockaddr *)&srvaddr,sizeof(srvaddr));

3.通信

while(1)
	{
		bzero(buf, 100);
		bzero(msg, 100);
		
		recvfrom(sock_fd,buf,sizeof(buf),0,(struct sockaddr *)&multiaddr, &addrlen);//先接收
		
		printf("recv:%s\n",buf);
		
		fgets(msg,sizeof(msg),stdin);
		
		sendto(sock_fd,msg,sizeof(msg),0,(struct sockaddr *)&cliaddr, addrlen);
		
	}

4.关闭套接字

close(sock_fd);

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值