我在C中编写一个“简单”点唱机,它是在Raspberry Pi上运行的,而且我很难找出优化其性能的最佳方法。
它的设置方式是我有一个处理所有图形(通过ncurses)和数据处理的进程,另一个我将命令发送到mp3播放应用程序(xmms2)然后我连接两个使用两个管道形成一个简单的桥接器,它发送诸如“获取当前播放列表位置”之类的消息并以“当前播放列表位置:0”响应(尽管不是那么冗长)。
所有管道都设置为非阻塞,但在发送这些命令时仍然会遇到很多延迟。
意识到这可能是一个抽象的问题,但我不是非常精通C,并且会欣赏任何类型的输入,无论是否我都完全走错了方向或者不是这样已经成立。
提前致谢!
主循环:
init_xmms_bridge();
pid_t pid = fork();
while(true == true)
{
update_xmms_bridge(pid);
if(pid != 0)
update_screen();
}
graphics.c
void update_screen(void)
{
/* update playlist if that has changed,
library display if keys has been pressed etc */
usleep(50000); // Wait .05 seconds
refresh(); // Refresh ncurses screen
}
xmms_bridge.c(部分)
void init_xmms_bridge(void)
{
pipe(xmms_pipe_in);
pipe(xmms_pipe_out);
// Set all pipes as non-blocking
int flags = fcntl(xmms_pipe_in[0], F_GETFL, 0);
fcntl(xmms_pipe_in[0], F_SETFL, flags | O_NONBLOCK);
flags = fcntl(xmms_pipe_in[1], F_GETFL, 0);
fcntl(xmms_pipe_in[1], F_SETFL, flags | O_NONBLOCK);
flags = fcntl(xmms_pipe_out[0], F_GETFL, 0);
fcntl(xmms_pipe_out[0], F_SETFL, flags | O_NONBLOCK);
flags = fcntl(xmms_pipe_out[1], F_GETFL, 0);
fcntl(xmms_pipe_out[1], F_SETFL, flags | O_NONBLOCK);
}
// Receive data from pipes
void update_xmms_bridge(pid_t process_id)
{
if(process_id == 0) // Child process
{
close(xmms_pipe_out[1]);
bytes_read_out = read(xmms_pipe_out[0],xmms_pipe_buffer_out,sizeof(xmms_pipe_buffer_out));
if(bytes_read_out != -1)
xmms_receive_call(xmms_pipe_buffer_out,XMMSDirectionOut);
}
else
{
close(xmms_pipe_in[1]);
bytes_read_in = read(xmms_pipe_in[0],xmms_pipe_buffer_in,sizeof(xmms_pipe_buffer_in));
if(bytes_read_in != -1)
xmms_receive_call(xmms_pipe_buffer_in,XMMSDirectionIn);
}
}
// Send data to pipes
void bridge_call(int pipe[2],const char command,char *parameters)
{
// Make sure it works even if parameters is null
char call[parameters == NULL ? 3 : strlen(parameters)+3];
/* Add separator to deal with the fact
that multiple calls can be made before
the loop reads the pipe. */
call[0] = SEPARATOR_CHARACTER;
call[1] = command;
call[2] = '\0';
// Concentate string before sending through pipe
if(parameters != NULL)
strcat(call,parameters);
close(pipe[0]);
write(pipe[1],call,strlen(call));
}
void xmms_bridge_call(const char command,char *parameters)
{
bridge_call(xmms_pipe_out,command,parameters);
}
void jukebox_bridge_call(const char command,char *parameters)
{
bridge_call(xmms_pipe_in,command,parameters);
}
答案 0 :(得分:0)
在阅读了Kenneth指出的用户之后,我通过用线程替换了分叉过程解决了这个问题。由于我的大多数调用应该是单向调用,因此我的典型线程代码如下所示:
pthread_t thread;
pthread_attr_t thread_attr;
int thread_error;
thread_error = pthread_attr_init(&thread);
if(thread_error)
{
/* Handle error */
return;
}
/* Make thread detached so I don't need to worry about it after it's creation */
result = pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
if(!thread_error)
{
thread_error = pthread_create(&thread,&thread_attr,<xmms-calling-funtion>,<arguments>);
pthread_attr_destroy(&thread_attr);
if(thread_error)
/* Handle error */
}
else
/* Handle error */
正如用户Craig所说,有一个xmms2 C客户端库,但我从未设法将它链接到我的程序,尽管我确信最好使用它。我仍然觉得这个答案更多地涉及我的问题,更多的是关于Raspberry Pi的性能而不是xmms2。
如果有人在Raspberry Pi上构建项目并成功将其链接到xmms2 C客户端库,我很想知道你是如何做到的!
链接到客户端库教程存储库:
git://git.xmms2.org/xmms2/xmms2-tutorial.git
对于好奇的人来说,这就是用户界面最终看起来像: