This time, Remote Development of Visual Studio Code I want to try Linux System Programming (C language) in Ubuntu of Azure Virtual Machine using the extensionpack) function. I think.
I prepared helloworld to try it out for the time being. Also, as a form close to actual development, I will try remote debugging using nginx as a subject.
--helloworld development and remote debugging --Development and remote debugging of nginx
Create an Ubuntu Virtual Machine. The points are as follows.
--This time, Ubuntu Server 18.04 LTS -Gen1 is used as the Linux Virtual Machine. --Authentication Type uses SSH Public Key --Inbound ports are set to 22 (SSH) and 8080 (used in the latter half of nginx)
As you all know about creating a Virtual Machine, you can skip it, but please create it according to the above.
From the Microsoft Azure portal screen, select Create a resource to create a Virtual Machine. Select Ubuntu Server 18.04 LTS -Gen1 as shown below. After making your selection, press Review + Create.
When you press Create on the confirmation screen, the Download Private Key and Create Virtual Machine buttons will be displayed. Press them again. Please save the Private Key so that you do not lose it, as you will need it when using it with SSH on the created Ubuntu.
After the Virtual Machine is created, check the IP address of the connection destination from the Virtual Machine screen.
After installing Visual Studio Code on Windows 10, set up remote development. (MacOS is also the same, but this time, it is amazing that the actual Linux System Programming can be done on that Windows, so I will proceed with Windows 10)
First of all, please download Visual Studio Code from the following site. https://code.visualstudio.com/
Run the downloaded installer to install it. You will be asked to select a task to add during installation, but this time I set it as follows. A Visual Studio Code shortcut will be created on your desktop, which you should use when running it in this article.
After starting Visual Studio Code, install the extensions from the Extensions icon on the left (① in the figure below). Enter the following extension name in the search box (② in the figure below) to search. When the extension is displayed, press Install (③ in the figure below) to complete the installation.
Extension name: Remote Development ms-vscode-remote.vscode-remote-extensionpack https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack
When Remote Development is installed, you will see a green button at the bottom left, click on it.
From the green button at the bottom left, select "Remote-SSH: Open Configuration File ..." to register the ssh connection destination. Set the HostName to the public IP address of the Virtual Machine and the IdentityFile to the Private Key downloaded when the Virtual Machine was created.
.ssh/config
Host linuxsystemprograming-vm
HostName xxx.xxx.xxx.xxx
IdentityFile C:\Users\kentaro\Downloads\linuxsystemprograming-vm_key.pem
User azureuser
Next, select "Remote-SSH: Connect to Host ..." from the green button at the bottom left, select the connection destination you registered earlier, and select Linux as the platform to connect. Now that you are logged in to the Azure Virtual Machine, install the packages required for development on the Ubuntu side. Select New Terminal from the Terminal menu to display the Ubuntu Terminal for the Azure Virtual Machine.
In Terminal, type the following command to install gcc and gdb on Ubuntu for your Azure Virtual Machine.
sudo apt update
sudo apt install -y build-essential gdb
From Terminal, create a directory on Ubuntu for Azure Virtual Machine and create a Hello World C language file.
cd /home/azureuser/
mkdir helloworld
cd helloworld
touch helloworld.c
From the Explore icon in the upper right, open the directory / home / azureuser / helloworld you just created.
When you select helloworld.c displayed in Explore, a message to install the C / C ++ extension is displayed in the lower right, so select install. (If you don't see it, install the C / C ++ extensions from the Extensions on the left)
Reloading is required, so please reload from the reload button on the center of the screen.
The source code of helloworld.c is as follows.
helloworld.c
#include <stdio.h>
int main(int argc, char *argv[])
{
int i;
for (i = 3; i > 0; i--)
{
printf("%d...\n", i);
}
printf("Hello World!\n");
return 0;
}
Make sure IntelliSense is enabled in Visual Studio Code.
After entering, save it with Ctl -s.
Select Configure Default Build Task ... from the Terminal menu, then select C / C ++: gcc build active file.
Since it will be editing taks.json, set as follows. (I haven't changed what was created automatically)
task.json
{
"version": "2.0.0",
"tasks": [
{
"type": "shell",
"label": "C/C++: gcc build active file",
"command": "/usr/bin/gcc",
"args": [
"-g",
"${file}",
"-o",
"${fileDirname}/${fileBasenameNoExtension}"
],
"options": {
"cwd": "${workspaceFolder}"
},
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
}
}
]
}
Make sure you can build from "Run Build Task ..." in the Terminal menu. A helloworld executable file will be created so you can run it.
Select "Add Configuration ..." from the Terminal menu, select "C ++ (GDB / LLDB)", and select "gcc --Build and debug active file" to set the debugging method.
launch.json
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "gcc - Build and debug active file",
"type": "cppdbg",
"request": "launch",
"program": "${fileDirname}/${fileBasenameNoExtension}",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"preLaunchTask": "C/C++: gcc build active file",
"miDebuggerPath": "/usr/bin/gdb"
}
]
}
After completing the settings, with Helloworld.c selected, press F5 or select "Start Start Debugging" from the Run menu to debug helloworld. You can also set breakpoints by clicking on the left side where the number of lines is displayed, you can step through and check the value of the variable.
Next, let's debug and execute nginx running on Ubuntu of Azure Virtual Machine.
Hello World is not practical, so I would like to develop and debug with Visual Studio Code using nginx as a subject.
Download the nginx source code and set up the nginx development environment. Also, install the packages required to build nginx.
sudo apt install -y libpcre3-dev libz-dev
cd ~/
wget https://nginx.org/download/nginx-1.19.2.tar.gz
tar xvfz nginx-1.19.2.tar.gz
cd nginx-1.19.2/
Let's try building nginx for debugging. Make sure you can build without errors.
cd ~/nginx-1.19.2/
./configure --with-cc-opt="-O0" --prefix=`pwd`/nginx
make
Select "Open Folder ..." from the Visual Studio Code File menu to open the nginx directory (/home/azureuser/nginx-1.19.2). I think you can use IntelliSense.
Also, since this development will be carried out by azureuser, change the listen port of nginx to 8080 etc. Change the port setting around line 36 in conf / nginx.conf to 8080. (If you are doing make install, change nginx / conf / nginx.conf as well)
Select Configure Default Build Task ... from the Terminal menu, then select C / C ++: gcc build active file.
task.json
{
"version": "2.0.0",
"tasks": [
{
"type": "shell",
"label": "C/C++: gcc build active file",
"command": "/usr/bin/make",
"args": [
"install"
],
"options": {
"cwd": "${workspaceFolder}"
},
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
}
}
]
}
Make sure you can build from "Run Build Task ..." in the Terminal menu. After the build, nginx will be installed in /home/azureuser/nginx-1.19.2/nginx.
After selecting /home/azureuser/nginx-1.19.2/src/core/nginx.c, select "Add Configuration ..." from the Terminal menu, select "C ++ (GDB / LLDB)", and then select "C ++ (GDB / LLDB)". Select gcc --Build and debug active file to set the debugging method. nginx sets the option not to run in the daemon. Also, stopAtEntry is set to true so that it can be stepped at runtime.
launch.json
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "gcc - Build and debug active file",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/nginx/sbin/nginx",
"args": ["-g", "daemon off;"],
"stopAtEntry": true,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"preLaunchTask": "C/C++: gcc build active file",
"miDebuggerPath": "/usr/bin/gdb"
}
]
}
Before you debug, make sure that the Azure Virtual Machine's Inbound security rule allows port 8080.
From Terminal, install and run nginx.
cd ~/nginx-1.19.2/
make install
./nginx/sbin/nginx -g "daemon off;"
In a web browser, access the Azure Virtual Machine public IP address port 8080 and verify that nginx is running. After checking, exit with Ctl -c.
With /home/azureuser/nginx-1.19.2/src/core/nginx.c selected, press F5 or select "Start Debugging" from the Run menu to debug nginx.
You can debug!
As a test, set a breakpoint immediately after waiting for a request from a web browser. It is around line 802 of /home/azureuser/nginx-1.19.2/src/event/modules/ngx_epoll_module.c.
800: events = epoll_wait(ep, event_list, (int) nevents, timer);
801:
802: err = (events == -1) ? ngx_errno : 0;
Since this is the part that runs as a worker process (child process) after starting nginx, set it to attach to the child process with gdb before being forked. Enter the gdb command at the bottom of DEBUG CONSOLE while debugging Visual Studio Code.
-exec set follow-fork-mode child
Also, if you want to check the current status, it will be as follows.
-exec show follow-fork-mode
Once set to gdb, continue running with "Continue" (a triangle icon like play). When you access the Azure Virtual Machine public IP address port 8080 again, the web browser goes into a wait state. This is because it stops at the breakpoint set in Visual Studio Code (gdb).
If you check the value returned from epoll_wait in Visual Studio Code, 1 is included. You can also step. Great! (man epoll_wait : https://linuxjm.osdn.jp/html/LDP_man-pages/man2/epoll_wait.2.html)
Also, if you want to set follow-fork-mode to child from the start of debugging, set setupCommands as shown below.
launch.json
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "gcc - Build and debug active file",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/nginx/sbin/nginx",
"args": ["-g", "daemon off;"],
"stopAtEntry": true,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "Set follow-fork-mode to child",
"text": "set follow-fork-mode child",
"ignoreFailures": true
}
],
"preLaunchTask": "C/C++: gcc build active file",
"miDebuggerPath": "/usr/bin/gdb"
}
]
}
Linux System Programming has become more familiar with Visual Studio Code and Azure Virtual Machine. It's like a dream to be able to remotely debug Linux running in the cloud.
If you want to write a server, please try it.
By the way, there are many books on TCP / UDP server program development, but many of them lack error handling, so I would like to introduce some recommended books for those who are studying from now on.
--UNIX Network Programming <Vol.1> W.Richard Stevens (It's a UNIX textbook book, but it's only used ...) https://amzn.to/335xUel
If you know the basic code of UNIX and want to deal with a large number of clients on a server with Linux, the following books are recommended.
--Linux programming interface Michael Kerrisk https://amzn.to/3j6ITKp --Linux System Programming Robert Love https://amzn.to/2GilXsM
I've read a bit of the nginx code for this article, but it's pretty, so it's a great learning experience.
Well then.