A bottom-up look or Ubuntu Server for an electronics developer. Part 2

    We continue to develop the theme of using a computer with ubuntu server as a device for connecting the world of microcontrollers with the world of personal computers.

    Link to Part 1
    image
    I recall that the article describes the practice of using the described technique and does not set out to cover all the depths and capabilities of modern equipment. This is one of the options for solving the problem.

    In this part, I will show you how to go through the following points:

    Static IP + DHCP Server
    Currently, only two devices are supposed to be in the local network. The server itself and the host machine. Based on this simplicity, we will configure the Ubuntu server.
    Static IP
    Reference information
    1. To find out the logical name of the network interface, do:

    sudo lshw -C network
    and look for a line
     logical name: enp3s0

    The option of using the ifconfig function (as an analog of ipconfig in windows) can sometimes give only loop 127.0.0.1. The name of the interface is hardware dependent. On two different machines, I installed ubuntu from the same flash drive and there were different names of network interfaces. enp3s0 is a classification by bus and device number, as I understand it. There are also from such a series eth0 and such ens35. Do not be alarmed.

    2. Modify the network configuration file

    sudo nano /etc/network/interfaces
    (nano is this little text editor)
    It should be like this:

    	# This file describes the network interfaces available on your system
    	# and how to activate them. For more information, see interfaces(5).
    	source /etc/network/interfaces.d/*
    	# The loopback network interface
    	auto lo
    	iface lo inet loopback
    	# My local network.
    	allow-hotplug enp3s0
    	iface enp3s0 inet static
    	address 172.16.55.1
    	netmask 255.255.255.0
    	gateway 172.16.55.1
    

    Press cntrl-x - to exit the editor.
    Press y - to save the changes

    . 3. Restart the network service:
    service networking restart


    DHCP server
    Basic information
    1. Editing files for the DHCP server
    sudo nano /etc/default/isc-dhcp-server
    find the line
    INTERFACES=""
    Is the name of the interface for the DHCP server. In our case, it should be like this:

    INTERFACES="enp3s0"

    In file
    sudo nano /etc/dhcp/dhcpd.conf
    need to add
    subnet 172.16.55.0 netmask 255.255.255.0{
     range 172.16.55.2 172.16.55.100;
    }
    Within this subnet, the DHCP server will issue addresses in the range from 2 to 100.

    2. If you use the gethostbyname () function, then in the file
    sudo nano /etc/hosts
    The name of the PC and IP should be written. Perhaps there is a more convenient way to get your own IP, but he did not give in to me.
    127.0.0.1	localhost
    172.16.55.1	ubuntu

    The name of the pc (ubuntu) is stored in the / etc / hostname file. Can look through
    sudo cat /etc/hostname
    and a million more ways.

    3. Reboot the network service:
    service networking restart

    SSH access
    In theory, having connected a stationary computer now, we will get an IP for it and will be able to access it via SSH. For access from Windows, I used the PuTTY utility. There, in the PuTTY program files, there is a utility for transmitting data over the network.
    Here is the composition of the batch file for transferring files from Ubuntu to Windows.
    d:\"Program Files"\PuTTY\pscp.exe ubuntu@172.16.55.1:/home/ubuntu/tool/* "F:/WORK/SERVER/tool/"

    And to upload to the server
    d:\"Program Files"\PuTTY\pscp.exe "F:/WORK/SERVER/tool/*" ubuntu@172.16.55.1:/home/ubuntu/tool/


    We put the driver from FTDI
    FTDI drivers come in compressed form. The package contains the drivers themselves, libraries, examples of use and the README.pdf file, which was most interesting. From the D3XX Programmers Guide file, it’s never clear how to use the Linux driver. I even had to write FTDI support to those, since they respond promptly and on business. It would be possible not to write if I immediately opened this archive. But useful were the links they sent, examples of wiring and circuitry.
    As shown above, using the pscp utility from the PuTTY kit, we copy the driver to the server. I had d3xx-linux-i686-0.5.0.tar.bz2. We go into this folder on the server and do
    tar -xvf d3xx-linux-i686-0.5.0.tar.bz2

    Further, according to the FTDI instruction, we execute:
    cd linux-i686
    sudo rm -f /usr/lib/libftd3xx.so
    sudo cp -f libftd3xx.so /usr/lib
    sudo cp -f libftd3xx.so.0.5.0 /usr/lib
    sudo cp -f 51-ftd3xx.rules /etc/udev/rules.d
    sudo udevadm control --reload-rules
    


    Compiling the program
    I wrote the program in codeBlocks and, with the exception of certain points, including due to FTDI, it is compatible with Windows. It stopped compiling for Windows when I put the h file from the driver for linux D3XX there (there were no problems with the D2XX and FT232RL chip).
    Now makefile. Programmers
    already know why it is needed, just indicate the features: STATLIB = libftd3xx.a - indicate the name of the library for Linux
    CFLAGS = $ (DEPENDENCIES) -Wall -Wextra -std = c ++ 11 - enable c ++ 11
    makefile example for one main.cpp project file
    CC=g++
    UNAME := $(shell uname)
    ifeq ($(UNAME), Darwin)
    	DEPENDENCIES := -lpthread -ldl -lobjc -framework IOKit -framework CoreFoundation
    else
    	DEPENDENCIES := -lpthread -ldl -lrt
    endif
    CFLAGS=$(DEPENDENCIES) -Wall -Wextra -std=c++11
    STATLIB=libftd3xx.a
    APP = prgr
    all: $(APP)
    $(APP): main.o 
    	$(CC) -o $(APP) main.o $(STATLIB) $(CFLAGS)
    main.o: main.cpp
    	$(CC) -c -o main.o main.cpp $(CFLAGS)
    clean:
    	rm -f *.o ; rm $(APP)
    

    Thus, the main.c ftd3xx.h makefile libftd3xx.a and other project files are in the project folder. And to compile the project now you need to go into this folder and do
    make


    daemon
    The role of daemons on Linux is similar to the role of services on Windows. These are programs that live in the background and do all kinds of peripheral work. It all starts with systemd, the program that starts first, has PID = 1, respectively, and starts all other background tasks through scripts. Digging into Ubuntu, I was surprised how much of everything inside is built on scripts. You have already seen how static IP changes, programs are configured, by simple correction of files in a text editor.

    By completing
    ps -el
    You will see a list of running programs with their PID. PID is a mandatory identifier of a running program, according to which the OS monitors this program. In extreme situations, you can bang the program for this PID from the terminal - write kill and PID (it may come in handy for debugging).

    So, when the daemon starts, a script is executed that indicates when and how the program needs to be started, how to stop it or restart it. In order for the daemon to work normally, the program at startup must save to the file, the path to which is specified in the script, its PID and switch to another stream (in the background).

    The demon guide led me into sadness and longing. Having greatly simplified the daemon, I turned it into a utility for launching any program. But the mandatory part has not changed. In addition, he logs to check if something happens.

    daemon code
    void SetPidFile(char* Filename)
    {
        FILE* f;
        f = fopen(Filename, "w+");
        if (f)
        {
            fprintf(f, "%u", getpid());
            fclose(f);
        }
    }
    int main( int argc, char** argv )
    {
        char toolfile[32];
        char folder[32];
        intptr_t ret;
        FILE* logfile;
        if( argc!=3 )
        {
            printf( "Write address of the program and name: /home/ubuntu/tool/ tool\n");
            return -1;
        }
        pid_t pid, sid;
        pid = fork();
        if (pid < 0)
        {
            sleep(1);
            return -1;
        }
        //We got a good pid, Close the Parent Process
        if (pid > 0) {
            return 0;
        }
        //Create a new Signature Id for our child
        sid = setsid();
        if (sid < 0)
        {
            return -1;
        }
        //Change File Mask
        umask(0);
        //Save PID
        memcpy( toolfile, argv[0], strlen(argv[0]) );
        memcpy( toolfile + strlen(argv[0]), ".log", 4 );
        memset( toolfile + strlen(argv[0]) + 4, 0, 1 );
        printf( "Daemon:: log to:%s\n", toolfile );
        logfile = fopen( toolfile, "w" );
        fprintf( logfile, "Daemon:: started with 0=%s 1=%s 2=%s\n", argv[0], argv[1], argv[2] );
        memset( toolfile, 0, 32 );
        memcpy( toolfile, argv[0], strlen(argv[0]) );
        memcpy( toolfile + strlen(argv[0]), ".pid", 4 );
        memset( toolfile + strlen(argv[0]) + 4, 0, 1 );
        SetPidFile( toolfile );
        fprintf( logfile, "Daemon:: PID=%u saved in the %s\n", getpid(), toolfile );
        memset( folder, 0, 32 );
        memcpy( folder, argv[1], strlen(argv[1]) );
        fflush ( logfile );
        memset( toolfile, 0, 32 );
        memcpy( toolfile, folder, strlen(argv[1]) );
        memset( toolfile + strlen(argv[1]), '/', 1 );
        memcpy( toolfile + strlen(argv[1]) + 1, argv[2], strlen(argv[2]) );
        //Change Directory
        //If we cant find the directory we exit with failure.
        if ((chdir(folder)) < 0)
        {
            fprintf( logfile, "Daemon:: Program folder was not found:%s\n", folder );
            fclose( logfile );
            return -1;
        }
        //Close Standard File Descriptors
        close(STDIN_FILENO);
        close(STDOUT_FILENO);
        close(STDERR_FILENO);
        fprintf( logfile, "Daemon:: Program started\n" );
        fflush ( logfile );
        ret = execl( toolfile, folder, NULL );
        if( ret==-1 )
        {
            fprintf( logfile, "Daemon:: execl error: %s. File=%s Folder=%s\n", strerror(errno), toolfile, folder );
            fclose( logfile );
            return -1;
        }
        fprintf( logfile, "Daemon:: closed\n" );
        fclose( logfile );
        return 0;
    }
    

    Compile the demon.

    At the moment, in our working directory, let's say / home / ubuntu / daemon /, we have:

    daemon -
    prgr daemon program -
    prgr.strt program - script that needs to be executed before the program starts (if necessary)
    prgr.stop - script that you need run to stop the program (if necessary)

    It is necessary to allow the programs to work:

    sudo chmod 755 ./tool
    sudo chmod 755 ./daemon

    Now we need a script for systemd.
    Do
    sudo nano /etc/systemd/system/mydaemon.service
    and write our script there.

    mydaemon.service
    [Unit]
    Description=my service
    After=network.target
    After=isc-dhcp-server.service
    [Service]
    Type=forking
    PIDFile=/home/ubuntu/daemon/daemon.pid
    ExecStartPre=/bin/sh /home/ubuntu/daemon/prgr.strt
    ExecStart=/home/ubuntu/daemon/daemon /home/ubuntu/daemon/prgr prgr
    ExecStop=/bin/sh /home/ubuntu/daemon/prgr.stop
    Restart=always
    TimeoutSec=5
    [Install]
    WantedBy=multi-user.target
    

    In the script, briefly:
    Description - a short name-description
    After - what is required to run
    Type = forking - systemd assumes that the service starts once and the process branches with the completion of the parent process.
    PIDFile - file with the PID of the program from the
    ExecStartPre daemon - before starting the
    ExecStart program - program with the
    ExecStop parameters - how to stop
    WantedBy - the level at which to start

    Now you can try to start everything.
    We write
    systemctl daemon-reload
    systemctl status mydaemon

    If everything is error-free, then run:
    systemctl start mydaemon

    After that, see the demon’s log, everything should go.
    To make autoload work
    systemctl enable mydaemon


    Friends, I look forward to your interesting comments and valuable advice. If you lied where - do not get very angry, just indicate what can be done better. I hope that part 3 will appear about a large script, auto-installation ... maybe something else.

    Also popular now: