最近公司项目需要把原本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;
}