Linux開發筆記暨Linux常用代碼

最近公司項目需要把原本windows的代碼搞成可跨平臺的,過程中遇到一些跨平臺方面的細節,記錄在這裏。

 

1、Linux端口檢測

檢測端口是否被佔用,這個在windows平臺下一般用GetTcpTable系統API來實現。而在Linux下沒有直接的API,在網上看看了最終提出一個解決方案,就是通過調用bind來判斷端口是否被佔用。如果有其他更好的解決方案麻煩告知一下。

#include <sys/socket.h>
#include <netinet/in.h>

bool checkPort(int port)
{
	int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	struct sockaddr_in servaddr;
	int on = 1;
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(port);
	if (bind(fd, (struct sockaddr *)&servaddr, sizeof(servaddr)) != 0)
	{
		cout << "false" << endl;
		return false;
	}
	else
	{
		close(fd);
		cout << "true" << endl;
		return true;
	}
}

2、Linux切換執行目錄,獲取當前程序運行目錄

這些功能在程序需要執行外部批命令的時候需要用到。Windows下可以直接調用系統API獲得,Linux下解決方案如下。

void changePathTest()
{
	system("mkdir test1");
	chdir("/root");//更改運行目錄
	system("mkdir test2");
	char path[255];
	readlink("/proc/self/exe", path, sizeof(path));//獲取當前程序路徑
	cout << string(path).substr(0, string(path).find_last_of('/')).data() << endl;//獲取程序的目錄
	chdir(string(path).substr(0,string(path).find_last_of('/')).data());//更改回本來的目錄
	system("mkdir test3");
}

3、Linux判斷目錄或文件是否存在、Linux創建目錄

這些功能其實在Linux下實現起來更簡單一些

	if (access(path, F_OK) != -1)  //判斷路徑是否存在
	{
		
		cout << path << " exists" << endl;
	}
	
	if(mkdir(string("mkdir " + string(path) + "test").data(), 00666) != 0)//創建目錄,所有用戶可讀可寫
	{
		cout << "fail" << endl;
	}

4、Linux根據進程名獲取pid和安裝路徑

void getPidByName(char * task_name)
{
	DIR *dir;
	struct dirent * ptr;
	FILE *fp;
	char file_path[MAX_PATH];
	char cur_task_name[MAX_PATH];
	char buf[BUF_SIZE];
	dir = opendir("/proc");
	int pid = 0;
	if (NULL != dir)
	{
		
		while ((ptr = readdir(dir)) != NULL)//循環讀取路徑下的每一個文件和文件夾
		{
			//如果讀取到的是"."或者".."則跳過,讀取到的不是文件夾名字也跳過
		 if((strcmp(ptr->d_name, ".") == 0) || (strcmp(ptr->d_name, "..") == 0))
			 continue;
			if (DT_DIR != ptr->d_type)
				continue;

			sprintf(file_path, "/proc/%s/status", ptr->d_name);   //生成要讀取的文件的路徑
			fp = fopen(file_path, "r");   //打開文件
			if(NULL != fp)
			{
				if (fgets(buf, BUF_SIZE - 1, fp) == NULL)
				{
					fclose(fp);
					continue;
				}
				sscanf(buf, "%*s %s", cur_task_name);

				//如果文件內容滿足要求則打印路徑的名字(即進程的PID)
				if(!strcmp(task_name, cur_task_name))
				{
					printf("PID:  %s\n", ptr->d_name);
					char path[255];
					readlink((string("/proc/")+ptr->d_name+"/exe").data(), path, sizeof(path)); //獲取程序路徑
					cout << "path: " << path << endl;
					
				}

				fclose(fp);
			
			}
		}
	}
    closedir(dir);
}

5、Linux下通配符遍歷文件、遞歸遍歷、文件名匹配

void fnmatchTest(string path, const string &pattern)
{
	DIR *dir;
	struct dirent *entry;
	
	dir = opendir(path.c_str());
	if (NULL != dir)
	{
		
		while ((entry = readdir(dir)) != NULL)
		{
			if ((strcmp(entry->d_name, ".") == 0) || (strcmp(entry->d_name, "..") == 0))
				continue;
			if (DT_DIR == entry->d_type)
			{
				fnmatchTest(path + "/" + entry->d_name, pattern);	
			}
			
			if (DT_REG == entry->d_type)
			{
				int ret = fnmatch(pattern.c_str(), entry->d_name, FNM_PATHNAME | FNM_PERIOD);
				if (ret == 0)
				{
					cout << path + "/" + entry->d_name << endl;
				}
			}
		}
	}
    closedir(dir);
}

6、Linux下獲取文件時間

void getFileModifyTime(char *file)
{
	struct stat s;
	lstat(file, &s);
	time_t  st_time= s.st_mtime;
	tm  *tm_ = localtime(&st_time);
	char buf[64];
	strftime(buf, 64, "%Y-%m-%d %H:%M:%S", tm_); 
	std::cout << buf << std::endl; 
}

7、Linux文件讀寫

 linux下的文件描述符是一個非負整數,標準輸入輸出等都是一個文件描述符。下面代碼是《UNIX環境高級編程》上的一個實例。可以實現任何文件的複製。

int main(int argc, char *argv[])
{
	int n;
	char buf[1024];
	while ((n = read(STDIN_FILENO, buf, 1024)) > 0)
	{
		
		if (write(STDOUT_FILENO, buf, n) != n)
		{
			
			cout << "write error" << endl;
		}
		if (n < 0)
		{
			
			cout << "read error" << endl;
		}
	}
	return 0;
}

8、Linux通過va_list,va_start,va_end實現可變參數格式化

std::string str_fmt(const char * _Format, ...)
{
	
	va_list arg_list2, arg_list1;
	va_start(arg_list1, _Format);
	va_copy(arg_list2, arg_list1);
	size_t num_of_chars = vsnprintf(0, 0, _Format, arg_list2);
	va_end(arg_list2);
	std::string _str;
	_str.resize(num_of_chars);
	
	vsnprintf((char *)_str.c_str(), num_of_chars + 1, _Format, arg_list1);
	va_end(arg_list1);


	return _str;
}

9、Linux下通過管道自定義core文件生成目錄、名稱等信息

#include <stdio.h>
#include <iostream>
#include <fstream>
#include <string>
#include <fcntl.h>
#include <time.h>
#include <unistd.h>
#include<algorithm>
using namespace std;
int main(int argc,char *argv[]) 
{ 
	
	char ll[10];
	int i = 10 / 0;

	cout << "dsadsa" << endl;
	string exe_path;
	string exe_file_name;
	if (argc > 2)
	{
		exe_file_name =  argv[1];
		exe_path = argv[2];
	}
	
	replace(exe_path.begin(), exe_path.end(), '!', '/');
	size_t index = exe_path.find_last_of('/');
	if (index == string::npos)
	{
		return -1;
	}
	exe_path = exe_path.substr(0, index+1);
	
	
	struct tm *t;
	time_t tt;
	time(&tt);
	t = localtime(&tt);
	char current_time[256];
	sprintf(current_time,"%4d%02d%02d%02d%02d%02d", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
	
	
	string core_file = exe_path + "core." + exe_file_name +"_" +string(current_time);

	int fd = open(core_file.c_str(),O_WRONLY|O_CREAT,0666);
	int n;
	char buf[4096];
	while ((n = read(STDIN_FILENO, buf, 4096)) > 0)
		write(fd, buf, n);
	cout << "over" << endl;

	return 0;
}

10、boost:thread線程控制

#include <iostream>
#include <chrono>
#include <boost/thread.hpp>
using namespace std;

class MyTask
{
public:
	void task()
	{


		try
		{

			while (true)
			{
				cout << "hello world!" << endl;
				boost::this_thread::sleep_for(boost::chrono::seconds(2));
			}
		}
		catch (boost::thread_interrupted&)
		{
			cout << "stop!" << endl;
		}


	}

	void start()
	{
		if (!thread.joinable())
		{
			thread = boost::thread(&MyTask::task, this);
		}
		else
		{
			cout << "yijingqidong !" << endl;
		}
		//thread.detach();
	}

	void stop()
	{
		if (!thread.joinable())
		{
			cout << "yijingtingzhi" << endl;
		}
		else
		{
			thread.interrupt();
			thread.join();
		}
	}

private:
	boost::thread thread;




};

int main(int argc, char *argv[])
{
	MyTask task;
	task.start();
	task.start();
	task.start();
	boost::this_thread::sleep_for(boost::chrono::seconds(11));
	task.stop();
	task.stop();
	task.stop();
	boost::this_thread::sleep_for(boost::chrono::seconds(11));

	return 0;
}

11、std::thread線程控制

#include <iostream>
#include <chrono>
#include <thread>
#include <atomic>
#include <mutex>
#include <stdlib.h>
using namespace std;
 
 
class MyTask
{
 
 
 
public:
	MyTask()
		: m_bExit(false)
		, m_isrunning(false)
	{
 
	}
	void start()
	{
		if (!m_isrunning)
		{
			m_thread = std::thread(&MyTask::doTask, this);
			set_priority();
			m_isrunning = true;
		}
		else
		{
			cout << "yijingqidong" << endl;
		}
	}
 
	void stop()
	{
 
		if (m_bExit)
		{
			cout << "yijingtingzhi" << endl;
			return;
		}
		mutex_for_bExit.lock();
		m_bExit = true;
		mutex_for_bExit.unlock();
		m_thread.join();
	}
 
	void set_priority()
	{

		sched_param sch;
		sch.sched_priority = 99;
		if (pthread_setschedparam(m_thread.native_handle(), SCHED_FIFO, &sch)) {
			std::cout << "Failed to setschedparam: "  << '\n';
		}

	}
 
private:
	void doTask()
	{
		while (!m_bExit)
		{
			cout << "Hello World!" << endl;
			this_thread::sleep_for(std::chrono::seconds(1));
		}
	}
	std::thread m_thread;
	std::mutex mutex_for_bExit;
	atomic<bool> m_bExit;
	atomic<bool> m_isrunning;
 
};
 
 
 
 
int main(int argc, char *argv[])
{
	MyTask task;
	task.start();
	task.start();
	task.start();
	std::this_thread::sleep_for(std::chrono::seconds(11));
	task.stop();
	task.stop();
	task.stop();
	task.stop();
	task.start();
	std::this_thread::sleep_for(std::chrono::seconds(11));
	task.stop();
	task.start();
	std::this_thread::sleep_for(std::chrono::seconds(11));
	task.stop();
	std::this_thread::sleep_for(std::chrono::seconds(11));
	return 0;
}
 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章