嵌入式面试一

本文探讨了嵌入式系统中的文件系统选择,如JFFS2、YAFFS和EXT3,深入分析了实时系统中可重入函数的重要性及其实现方法。此外,文章还介绍了预防头文件重复包含的技巧,提供了实用的C语言编程示例,包括求阶乘和字符串统计,以及复杂的算法挑战,如寻找特定数学属性的整数。最后,通过一个网球场地分配系统的实例,展示了如何设计高效的资源管理系统。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.文件系统

JFFS2、YAFFS、EXT3

2. 可重入函数的条件有哪些

在实时系统的设计中,经常会出现多个任务调用同一个函数的情况。如果这个函数不幸被设计成为不可重入的函数的话,那么不同任务调用这个函数时可能修改其他任务调用这个函数的数据,从而导致不可预料的后果。那么什么是可重入函数呢?所谓可重入是指一个可以被多个任务调用的过程,任务在调用时不必担心数据是否会出错。不可重入函数在实时系统设计中被视为不安全函数。

 满足下列条件的函数多数是不可重入的:

  • 函数体内使用了静态的数据结构;
  • 函数体内调用了malloc()或者free()函数;
  • 函数体内调用了标准I/O函数。

如何写出可重入的函数?在函数体内不访问那些全局变量不使用静态局部变量,坚持只使用缺省态(auto)局部变量,写出的函数就将是可重入的。如果必须访问全局变量,记住利用互斥信号量来保护全局变量。或者调用该函数前关中断,调用后再开中断。

可重入函数可以被一个以上的任务调用,而不必担心数据被破坏。可重入函数任何时候都可以被中断,一段时间以后又可以运行,而相应的数据不会丢失。可重入函数或者只使用局部变量,即保存在CPU寄存器中或堆栈中;或者使用全局变量,则要对全局变量予以保护

3.C语言中如何防止头文件的重复定义

方式一:
#ifndef _TEST_H_
#define _TEST_H_
// c/c++语言标准支持,不受编译器限制
#endif

方式二:
#pragma once #编译器相关,不一定被支持
... ... // 声明、定义语句

 

4.程序的功能是求1到20的阶乘的和。

#include <stdio.h>

int main()
{
    long long sum = 1, total = 0;

    for(int i=1; i<=20; i++)
    {
        sum *= i;
        total += sum;
    }
    
    printf("%lld\n", total);
    
    return 0;
}

 5.输入一串字符,然后统计其中英文字母,空格,数字和其他字符的个数。

#include <stdio.h>

int main()
{
    char c;
    int letters = 0, space = 0, digit = 0, other = 0;
    while((c = getchar()) != '\n')
    {
        if((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
        {
            letters++;
        }
        else if(c == ' ')
        {
            space++;
        }
        else if(c >= '0' && c <= '9')
        {
            digit++;
        }
        else
        {
            other++;
        }
    }
    printf("字母数:%d\n空格数:%d\n数字数:%d\n其他字符:%d\n",letters,space,digit,other);
    return 0;
}

6.一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数。请输出n以内符合这样特征的整数个数。

#include <stdio.h>
#include <math.h>

int main()
{
    int n,i,j,t,count = 0;
    scanf("%d", &n);
    for(int i=1; i<n; i++)
    {
        t = i + 100;
        j = i + 268;

        if( t == (int)sqrt(t)*(int)sqrt(t) && j == (int)sqrt(j)*(int)sqrt(j))
            count++;
    }
    printf("%d\n", count);

    return 0;
}

7.有一个二叉树,现在怀疑它有一个结点有2个父节点,请写出一个函数来判断该二叉树是否存在一个节点含有2个父节点。如果存在,返回true,否则返回false。

要检测一个结点是否有两个父亲时,先把从该结点开始的结点与原树分离,分成两部分,然后再从原树再查找该结点,如果找到那就是有两个结点,如果没有则递归查找。

struct Node{
Node *pLeft;
Node *pRight;
int Data;
};
 
//pTree为要查找的树,pParent为pNode的父结点,pNode为根时pParent 为NULL
//若pTree 中存在具有两个父结点的点返回真,否则返回假
bool CheckTwoParent( Node *pTree, Node *pParent, Node *pNode)
{
    Node *pTemp = NULL;
    bool result;
    if ( pNode == NULL ) return false;
    if ( pParent == NULL )  //根结点
    {
        if ( pTree->pLeft != NULL )
        {
           pTree->pLeft = NULL;
           result = FindNode( pTree, pNode ); //FindNode为在pTree树中查看PNode结点存在与否,若存在返回true,否则返回false,这个很简单,可以自己写
           pTree->Left = pNode;
           if ( result ) return true;
        }
 
        if ( pTree->pRight != NULL )
        {
            pTree->pRight = NULL;
            result = FindNode( pTree, pNode );
            pTree->pRight = pNode;
            if ( result ) return true;
        }
 
       if ( CheckTwoParent( pTree, pNode, pNode->pLeft) ) return true;
       return CheckTwoParent( pTree, pNode, pNode->pRight);
 
    }
    else
    {
        if ( pParent->pLeft == pNode )  //若当前结点为左孩子
        {
            pParent->pLeft = NULL;
            result = FindNode( pTree, pNode ); //FindNode为在pTree树中查看PNode结点存在与否,若存在返回true,否则返回false,这个很简单,可以自己写
            pTree->Left = pNode;
            if ( result ) return true;
        }
        else
        {
            pParent->pRight = NULL;
            result = FindNode( pTree, pNode ); //FindNode为在pTree树中查看PNode结点存在与否,若存在返回true,否则返回false,这个很简单,可以自己写
            pTree->pRight = pNode;
            if ( result ) return true;
        }
 
       if ( CheckTwoParent( pTree, pNode, pNode->pLeft) ) return true;
       return CheckTwoParent( pTree, pNode, pNode->pRight);
    }
 
}

 

8.网球中心共有100个网球场,每个单位可以来申请1到100的场地,申请的场地编号必须是连续的,如果场地已经被其他单位占用,就不能再次使用,而且单位在使用完场地后必须归还。请设计一个完整的系统。

#include <iostream>
#include <vector>
#include <string>

using namespace std;

//网球场
struct TennnisCourt
{
    int serialNum;//编号
    bool bOccupied;//是否被占用
    string Owner;//占用者
};

//网球中心
class TennnisCenter
{
public:
    TennnisCenter();

    void print() const;
    //请求num块场地,若分配成功,则返回分配的场地的编号
    bool requestCourts(int num, const char* requester, vector<int>& alloctedCourts);
    //归还连续编号的场地
    bool returnCourts(const char* returner, vector<int>& alloctedCourts);

    int getEmptyCourts() const;
protected:
    void init();
    void allocateCourts(int begin, int end, const char* requester);
    bool IsValidOwner(int begin, int end, const char* returner);
    void freeCourts(int begin, int end);
private:
    vector<TennnisCourt> courts; //场地
    int nEmptyCourt;    //空余的场地数目
    static const int MAX_CAPACITY = 100; //场地最大数目
};

TennnisCenter::TennnisCenter()
{
    this->init();
}

void TennnisCenter::init()
{
    nEmptyCourt = MAX_CAPACITY; //空余块场地

    courts.resize(MAX_CAPACITY);

    for(int i=0; i<MAX_CAPACITY; i++)
    {
        courts[i].serialNum = i+1;
        courts[i].bOccupied = false;
        courts[i].Owner = "";
    }
}

void TennnisCenter::print() const
{
    vector<TennnisCourt>::const_iterator iter;

    for(iter = courts.begin(); iter != courts.end(); ++iter)
    {
        cout << iter->serialNum << '\t';
        if(iter->bOccupied)
            cout << iter->Owner << '\t';
        cout << endl;
    }
}

//申请begin到end的场地
void TennnisCenter::allocateCourts(int begin, int end, const char *requester)
{
    for(int i = begin; i <= end; i++)
    {
        courts[i].bOccupied = true;
        courts[i].Owner = requester;
        --this->nEmptyCourt;
    }
}

//是否是合法拥有者
bool TennnisCenter::IsValidOwner(int begin, int end, const char *returner)
{
    for(int i = begin; i <= end; i++)
    {
       if(courts[i].Owner.compare(returner) != 0)
           return false;
    }

    return true;
}

void TennnisCenter::freeCourts(int begin, int end)
{
    for(int i = begin; i <= end; i++)
    {
        courts[i].bOccupied = false;
        courts[i].Owner = "";
        ++this->nEmptyCourt;
    }

}

//请求num块场地,若分配成功,则返回true,输出参数中保存分配的场地的编号,否则返回false
bool TennnisCenter::requestCourts(int num, const char *requester, vector<int> &alloctedCourts)
{
    cout << "remian " << this->nEmptyCourt << " Courts" << endl;

    alloctedCourts.clear();

    bool result = false;

    if(num > this->nEmptyCourt)//剩余场地不够,不需再查看
        return false;

    //剩余场地数目够,看是否有足够连续多的场地满足用户请求
    int i,j,k;
    for(i = 0; i < MAX_CAPACITY; ++i)
    {
        //从i开始数num个,如果都为false,说明这连续的一段没被占用,可以申请
        for(j = i, k = 0; j < MAX_CAPACITY && k < num; j++,k++)
        {
            if(courts[j].bOccupied == true)
            {
                break;//有被占用,未能连续
            }
        }
        if(k == num)//有连续num个空场地,分配给请求者
        {
            this->allocateCourts(i, i+num, requester);

            for(k =i; k <i + num; k++)
            {
                alloctedCourts.push_back(k+1);
            }

            result = true;

            break;
        }
    }

    return result;
}

//归还连续编号的场地
bool TennnisCenter::returnCourts(const char *returner, vector<int> &alloctedCourts)
{
    int begin = alloctedCourts[0] - 1;
    int end = alloctedCourts[alloctedCourts.size()-1]-1;

    if(!this->IsValidOwner(begin, end, returner))
    {
        //非法持有者不能归还
        return  false;
    }

    this->freeCourts(begin, end);
    return true;
}

int TennnisCenter::getEmptyCourts() const
{
    return this->nEmptyCourt;
}

void showAllocatedCourts(const vector<int>& courts)
{
    vector<int>::const_iterator iter;
    for(iter = courts.begin(); iter != courts.end(); iter++)
    {
        cout << *iter << endl;
    }
}

int main()
{
    TennnisCenter tennisCenter;
    vector<int> allocatedCourts;
    bool result = tennisCenter.requestCourts(10, "liuxin", allocatedCourts);
    if(result)
    {
        showAllocatedCourts(allocatedCourts);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值