Detailed analysis of embedded architects without embedded software

Embedded here is specifically based on the Linux platform, microcontroller and other rtos are not in the scope of discussion ~

I have been engaged in embedded software development for 6 or 7 years, bsp, drivers, application software, android hall, framework, etc. are involved. In addition to paying attention to the development of the embedded industry, there are some concerns about the technologies of the Web, background server, and distributed.

Recently, I have the idea of ​​changing the direction of the industry. I want to do the development related to the background server. Since there is no actual demand in this work in the previous work, I just pay attention to it and understand some knowledge, such as: NIO, epoll, ngnix, zeromq, Libevent, libuv, high concurrency, distributed, redis, python, tornado, django, involved in more mixed, all know a fur, not fine. Unexpectedly, it has been repeatedly despised by the Internet industry, and there are very few interview opportunities.

At this point, I think what is the problem. Is it that the embedded origin has been so unsatisfied? I want to be embedded, drive development, but the industry is fascinating (somewhat exaggerated, but embedded 8 or 9 years ago) Listening is more important than doing java web.)

There are always reasons for the problem. I said my own understanding:

Is embedded really tall? Why are there no embedded software architects?

Open a variety of recruitment sites, search architects, there will be a variety of system architects, web architects, background server architects, etc., but only difficult to see embedded software architects. Does the embedded software not require an architecture, does the driver need an architecture? The answer is of course needed, but why is there no such position?

My view: At present, domestic embedded development is mainly divided into embedded low-level development and embedded application development. The embedded low-level development is generally called driver development, or bsp development. Sometimes it is called linux kernel development. Very high feeling.

Why are there no architects on such a tall name? Linux, kernel architect is a Linux kernel development and maintenance person such as linus, because its own Linux kernel or operating system is a general platform to solve the general problem, the Linux open source big cattle have already formulated the structural rules, stay There are not many places to play, and most of the work only needs to be filled according to the rules framework.

At present, the business needs of most domestic companies are only the integration of peripheral devices. The porting, building and cutting of embedded platforms and business requirements will not exceed the range of functions provided in the kernel, resulting in no new architecture requiring developers. Go to design and implement. What are the embedded bsp developers doing? In addition to debugging a variety of peripherals, cleaning the butt for the hardware, is to solve some of the stability of the bug (this is not detailed description of the specific work, debugging peripherals will only add some experience, increase the breadth, and contribute little to improve the depth , just press this route without debugging - "will debug -" debugging, and solving stability problems really needs some accumulated experience)

The embedded application development, the general business logic is relatively simple, and many people ignore it, so the recruiter will feel that there is no need to find the architect level.

At this point, I feel that the embedded industry does not need an architect, and there is nothing to be surprised by the contempt of the Internet industry.

But is this really the case? For the development of embedded underlying, there is the ability to optimize the architecture of the kernel and driver architecture. There should be not many domestic developers, so for most ordinary people, don’t “think” Linux. The architect of the kernel (of course, I believe that there must be a big cow with this ability in the country), and found that solving some bugs is more reliable.

So for the development of the embedded application layer, do we really need no architecture?

I used my actual experience to describe the architecture design and optimization of an embedded device application software: I have taken over a project that uses a single-process multi-threaded model with several modules, a, b, c , d, e stands for. The business logic of this project determines that there are many connections between these modules.

For example, in the original design, the a module is a status monitoring module, which calls b based on the monitored status. The interface of the c module implements some functions. The advantage of multi-threading is that it is convenient to call directly, so most developers are so simple and simple. rough). However, the demand is always changing. To add an f module, the f module also needs to process the status of the a module monitoring. According to the previous routine, this function is divided into two steps:

The interface is provided in the f module.

The interface is called in the a module, and the new requirements have been "perfectly" solved.

As mentioned above, the demand is always changing. The new demand is coming again. The customer proposes the customization requirement and needs to join another g module, and also handles the status of the a module monitoring, but the customization requirement does not need the f module just added. The easiest and most rude way is to define a macro that distinguishes between this customization requirement and the previous general requirements, building two program versions. This approach seems simple, but if the customization requirements are gradually increased, it is a nightmare to maintain so many customized versions of the program. Code management and versatility are also big problems, and the code is full of different definitions of different macros. deal with.

A good practice is to add dynamic monitoring of the device model version, dynamically support all customization requirements with a build version, which reduces the maintenance of different build programs. However, this method only solves the version maintenance work of the build program, and does not solve the problem of macro definition differentiation processing, but only changes the previous macro judgment to the dynamic device version number judgment, if these differentiated judgments are concentrated only in one place. Carrying on, it will not cause big complications, but obviously this is not guaranteed, it is possible that these different treatments will spread to all corners of the project, so that the project will become a nightmare.

No need for advanced software ideas, most people will think of extracting the differentiated parts and putting them in a unified place for centralized management. The changes to the differences will only be concentrated in this unified management.

The common practice is to use the callback to set the hook, then customize the differentiated requirements in the callback, and make a differential configuration for the callback processing. Corresponding to the above example, a hook is added in the a module, and then when the system is initialized, according to the device version. Different numbers, different custom callback processing functions, at the same time, these custom callback processing functions should be placed in the same place, otherwise it will be meaningless in all corners. (The former way is not to place the hooks without placing hooks.) Putting it together, another benefit of this processing is that our changes to the functional requirements will not affect the processing of the a module, that is, we add functionality, no need to modify the code of the a module (previous one) One way is to modify the calling process of a module, so that a module is separated.

At this point, the architecture of the second scheme (which is actually not the architecture) has been improved a lot compared to the first scheme, at least to make the developer a little easier. For other customization needs, the developer needs to modify this. Callback processing, pay attention to the differentiation part.

Software needs to be constantly evolving. Is the second solution the optimal solution? Of course not, is there room for optimization?

Let's run a question first, talk about the advantages and disadvantages of the multi-threaded/multi-process model, mainly on the advantages of multiple processes:

The explanation in the textbook is not mentioned. First of all, I am advocating the multi-process model for large projects. The main reasons are:

1. Decoupling of modules: Many developers maintain multi-threaded model projects that should have the following problems: Direct calls between modules, if you don't believe it, well, your project must be sub-module, now Randomly delete a module, build to see if you can build through (only need build does not need to run), I believe that in most cases will encounter a function call, a global variable can not be found, this kind of The situation shows that there is a strong coupling between your modules.

Due to the natural advantages of multi-threading, the address space is mutually visible, which makes it easy to call directly. Many engineers with little experience can easily write a simple and rude interface that is directly called. If a function of a static interface is encountered, the figure is convenient. It will also remove the static and take it directly. In this way, as the whole project is added with functions, the crossover between modules is more and more, and the coupling is higher.

The reason why I admire multi-process is that multi-process can physically isolate this "convenient" communication method. When I want to implement a module interaction, I will think more about this interaction. If it is If necessary, we will further consider whether the interface definition is simple and straightforward (because the communication between processes is relatively troublesome, the developer will carefully consider the interface, the definition of the protocol, in order to reduce the interaction and clear the interface, otherwise it will be tossing itself. )) This is like life. If you have been going smoothly, people may not think too much, think too much, and if there is some bumpy road, there will be another sentiment.

So my idea is that a multi-process model will force you to think more about the design of the program, physically reducing the coupling of the module.

Abstract generic components, separating common functions and business logic functions: When modifying a multi-threaded model into a multi-process model, it is often found that some interface code is repeatedly present in multiple process modules because the previous interface function is in one Process space, everyone can call directly, for example, interface A is called by module a, b, module a, b is separated into two independent processes, interface A needs to be implemented in a, b respectively, no need to explain, repeat code This is a big deal in software engineering and must be eliminated. The practice is also very simple, the interface that is called by multiple modules is separated into lib, which is called by other modules. When you complete this part of the work, what do you find, is the stripped interface, and can be used as the whole project. The component exists. In the perfect case, the code under lib is a common basic component, and each module is an independent business processing module.

2. Convenient positioning problem: When another thread exits abnormally in the multi-threaded model, the whole process will be exited. Of course, through some crash information, it can be located which thread is dead. However, if these thread modules are maintained by multiple teams and personnel, when the entire process crashes, how to determine which group to solve is a big problem. And sometimes the phenomenon that occurs is hanging in a thread, but it is caused by another thread module (coupling of the coupling), in this case, it is inevitable that there will be a gap between the groups. (confident engineers think that my code is fine)

And if you use a multi-process model, well, your service process hangs, you find the reason yourself, there is nothing to argue about.

3. Convenient performance test: multi-threaded single-thread resource occupancy is not very good to view (at least some embedded systems do not have perfect commands), when the entire process resource consumption is high, how to determine which module thread is located when positioning, the same The front question is just as difficult to decide. And if it is a multi-process model, whose process accounts for a lot of resources, whoever will check it out, in fact, this is still a problem of granularity. The same system is divided into multiple processes. The complexity of a single process must be lower than the complexity of only one process, the complexity is reduced, and it is easier to locate and find various problems.

4. Distributed deployment: The Internet industry has always emphasized the distribution, cloud, or whatever, the embedded industry is very hard, it seems that there is no need for distributed, in fact, right, in most cases, embedded using a single chip , running independently, distributed rarely encountered. But if you are in a device that day, the function of a chip is distributed to two chips, the multi-process expansion is much easier.

This is just a special example. In fact, embedded devices are a distributed industry, but they have been separated from the beginning, rather than from a centralized to distributed route.

Convenient for company code isolation: In fact, I despise this practice, the company must trust its employees, but in good faith in China already. . . It is understandable to do some isolation.

Under the multi-threaded model, the above mentioned that if you remove a module, you may not be able to build it. Is it necessary to expose all the code to all engineers? Obviously not, so each module can only provide the form of the library, but I think It is normal to organize common function interfaces into a common library, and if the modules related to the business are also provided as libraries, it is a bit. . . .

At this point, I would like to add that all the above advantages are not really critical points. They are not able to make multi-processes have an absolute advantage over the multi-threaded model. From a personal point of view, the multi-process model can force engineers to think about solving some problems. problem. (And those engineers with experience with these problems will think regardless of the model)

As mentioned above, it is necessary to change the example of the previous project into a multi-process model, otherwise it will only be on paper.

The first problem is: choose multi-process communication mode, direct call between multiple threads can not be used, then how to choose multi-process communication mode?

Linux provides a lot of ipc methods, not listed here, for the control of non-large data volume, communication message delivery, a better way is to use socket, the machine uses more unix socket mode, (this way there are What are the benefits? When you need to make a single system into a distributed system, the advantages are obvious.)

But just using the socket to implement the functions of the previous example, there will be some problems as well: the previous example, first of all, the second solution we optimized in the previous multi-process model can not continue to use, the reason is relatively simple, should not Need to explain.

The simple method is based on the first scheme, the direct call is changed to socket communication (the communication protocol can be defined), but the engineers familiar with the socket development are clear that the beginning of the socket communication must first carry out some preliminary work (mainly the connection, the two Modules are associated), so the previous example will become like this, module a should establish a connection with modules b, c, if you add f module, module a will also establish a connection with f module. In this case, if you draw a connection diagram in your heart, you will find that we have weaved a spider web. The relationship between nodes is intricate, and as with solution 1, we add a module associated with a, and we need to modify the code of module a. And this situation is much more complicated than the multi-threaded model. This practice is definitely a nightmare.

How to solve? I think a lot of people must have thought of the way to use bus distribution. Understand the development of android system will think of binder, understand openwrt will think of ubus, understand the desktop will think of dbus, the developers of the Internet industry must also know the sub/pub module provided in redis.

The above binder, ubus and other principles are very simple, is to establish a message center, build a forwarding routing model, all other modules do not directly interact, but use message center forwarding, routing, and how to determine routing rules, then use subscription / The observer mode is published to define the rules. (Embedded developers or C-language developers often mistakenly believe that design patterns are associated with object-oriented languages ​​and are unique to object-oriented languages. Although many of them have made this popular, given the information of some developers. The channel is relatively occluded, and this idea is still very popular)

Based on this model, the requirements of the above example are well solved. To join a message center module, all the modules that need to communicate are only connected to the message center module, and then subscribe to the events of interest to them. When the event occurs, only the event needs to be performed. The corresponding processing is fine.

Thus, the above module b, c subscribes to the event of module a. When module a detects an event, the event is released, the event first arrives at the message center, and is forwarded to the module b, c by the message center, and for the newly added module. f, you only need to subscribe to the module, without modifying the code to module a, making the function expansion very convenient.

At the same time, the above-mentioned customized development is also simplified. If the customized version needs to be added to the module g, then only the customized version is required to start the module g as a separate process, and then subscribe to the event of module a, and customize The difference between the version and the general version is whether to start the process of module g, thus achieving a goal of software engineering: the function is added like building blocks, only need to insert (start) or pull out (do not start) a module. The change of function is limited to one or several modules, and will have no effect on the main frame.

The above probably describes the process of gradual optimization of a project's requirements. The example seems to be based on embedded projects, but it seems to be equally applicable to software engineering.

Come to the Internet industry:

To view the articles shared by the major website architects on the technical architecture changes of this website, the first thing mentioned is that, based on the business, the previous application server function is split and more refined (such as e-commerce login, registration, transaction, Separation of business services such as merchandise, sellers, etc., and then deploy the split services on multiple servers to provide concurrency. Is there some familiarity here, and whether it is similar to the multi-threaded to multi-process partition mentioned earlier.

After the split, I also encountered communication problems. At this time, many message middleware came into being. For example, Ali's duboo, simply understand the principles of these middleware, nothing more than subscription release, RPC and other mechanisms, can be said to be similar, and difficult It is the improvement of the formulation and performance processing of the agreement.

In contrast to the Internet industry's load balancing solution, it seems that the load-balanced front end is also like a message center.

I have said so much above, just want to explain a problem. The design of software is the same. The idea based on it is the same. Although the business logic of the embedded industry is relatively simple, in fact, after careful consideration, there will still be many architectures. Improvement, design.

But what makes me sad is that some embedded developers, in view of the simplicity of the business logic, feel that using some less-than-good processing methods can solve the problem, not thinking about how to optimize and improve. For example, in the first example of the above example, if there are not many customization requirements, the maintenance is not too much problem. Even if the customization requirements are too much, then some junior programmers can also maintain it. One person is responsible for one set of code. The company of the project is not non-existent.

Similarly, the Internet industry and the embedded industry should not have a high wall that cannot be exceeded. We should pay more attention to the general software engineering thinking.

Tubular Stranding Machine

Tubular Stranding Machine

Tubular and planetary stranding machines for production of steel wire ropes.
Tubular rotor supported by bearing, bearing lubrication by centralized circulating oil.
Planetary cages supported by bearing or under roller, with back twist.
Lay length optional by gearbox or by electrical system.
Machine design customized.

Tubular Strander,Stranding Machine,Wire Stranding Machine,Tubular Stranding Machine

ROYAL RANGE INTERNATIONAL TRADING CO., LTD , https://www.royalrangelgs.com